1 /***************************************************************************//**
2 * \file cyhal_ezi2c.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon EZI2C.
6 * This interface abstracts out the chip specific details. If any chip specific
7 * functionality is necessary, or performance is critical the low level functions
8 * can be used directly.
9 *
10 ********************************************************************************
11 * \copyright
12 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
13 * an affiliate of Cypress Semiconductor Corporation
14 *
15 * SPDX-License-Identifier: Apache-2.0
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 *
21 *     http://www.apache.org/licenses/LICENSE-2.0
22 *
23 * Unless required by applicable law or agreed to in writing, software
24 * distributed under the License is distributed on an "AS IS" BASIS,
25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 * See the License for the specific language governing permissions and
27 * limitations under the License.
28 *******************************************************************************/
29 
30 /**
31 * \addtogroup group_hal_ezi2c EZI2C (Inter-Integrated Circuit)
32 * \ingroup group_hal
33 * \{
34 * High level interface for interacting with the Cypress EZ Inter-Integrated Circuit (EZI2C).
35 * The EZI2C driver implements an I2C slave device that emulates a common I2C EEPROM interface between
36 * the external master and your application code. EZI2C Slave buffers can be set up as any variable, array,
37 * or structure in your code without worrying about the I2C protocol. I2C related transactions and processing
38 * of data from the I2C master are handled by the driver through internal interrupt routine, reducing application
39 * involvement to maintain the I2C buffer.
40 *
41 * \section subsection_ezi2c_features Features
42 * * EZI2C Slave functionality
43 * * Configurable standard data rates of 100/400/1000 kbps - \ref cyhal_ezi2c_data_rate_t
44 * * Supports one or two addresses with independent memory buffers - \ref cyhal_ezi2c_cfg_t
45 * * Memory buffers provide configurable read/write and read only regions - \ref cyhal_ezi2c_cfg_t
46 * * 8 or 16-bit sub-addressing - \ref cyhal_ezi2c_sub_addr_size_t
47 * * Configurable interrupt and callback assignment from EZI2C events - \ref cyhal_ezi2c_event_t
48 *
49 * \section section_ezi2c_quickstart Quick Start
50 * Initialize EZI2C by using \ref cyhal_ezi2c_init and selecting the <b>sda</b> and <b>scl</b> pins.
51 * Setup one or two memory buffers and read/write boundaries using the EZI2C configuration
52 * structure \ref cyhal_ezi2c_cfg_t.
53 * See \ref subsection_ezi2c_snippet_1
54 * \note The clock parameter <b>clk</b> is optional and can be set to NULL to generate and use an
55 * available clock resource.
56 *
57 * \section section_ezi2c_snippets Code snippets
58 *
59 * \subsection subsection_ezi2c_snippet_1 Snippet 1: EZI2C Initialization and Configuration
60 * The following snippet shows how to initialize and configure an EZI2C and assign the pins to the <b>sda</b> and <b>scl</b> lines.
61 * The <b>clk</b> need not be provided (NULL), in which case a clock resource is assigned.
62 *
63 * \snippet hal_ezi2c.c snippet_cyhal_ezi2c_init
64 *
65 * \subsection subsection_ezi2c_snippet_2 Snippet 2: Register Callback function
66 * The following snippet shows how to use the \ref cyhal_ezi2c_register_callback function. The <b>callback</b> parameter
67 * refers to the handler which will be invoked when an event triggers.
68 *
69 * \snippet hal_ezi2c.c snippet_cyhal_ezi2c_handler
70 */
71 
72 #pragma once
73 
74 #include <stdint.h>
75 #include <stdbool.h>
76 #include "cy_result.h"
77 #include "cyhal_hw_types.h"
78 
79 #if defined(__cplusplus)
80 extern "C" {
81 #endif
82 
83 /** \addtogroup group_hal_results_ezi2c EZI2C HAL Results
84  *  EZI2C specific return codes
85  *  \ingroup group_hal_results
86  *  \{ *//**
87  */
88 
89 /** The requested resource type is invalid */
90 #define CYHAL_EZI2C_RSLT_ERR_INVALID_PIN                \
91     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_EZI2C, 0))
92 /** Can not reach desired data rate */
93 #define CYHAL_EZI2C_RSLT_ERR_CAN_NOT_REACH_DR           \
94     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_EZI2C, 1))
95 /** Number of addresses is not valid */
96 #define CYHAL_EZI2C_RSLT_ERR_NUM_ADDR_NOT_VALID         \
97     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_EZI2C, 2))
98 /** Number of addresses is not valid */
99 #define CYHAL_EZI2C_RSLT_ERR_CHECK_USER_CONFIG          \
100     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_EZI2C, 3))
101 
102 /**
103  * \}
104  */
105 
106 /** CYHAL_EZI2C_EVENT_NONE event is deprecated and that CYHAL_EZI2C_STATUS_OK should be used instead */
107 #define CYHAL_EZI2C_EVENT_NONE CYHAL_EZI2C_STATUS_OK
108 
109 /** Size of Sub-Address */
110 typedef enum
111 {
112     CYHAL_EZI2C_SUB_ADDR8_BITS,    /**< Sub-address is 8 bits  */
113     CYHAL_EZI2C_SUB_ADDR16_BITS    /**< Sub-address is 16 bits */
114 } cyhal_ezi2c_sub_addr_size_t;
115 
116 /** Data rate of the slave */
117 typedef enum
118 {
119     CYHAL_EZI2C_DATA_RATE_100KHZ = 100000,
120     CYHAL_EZI2C_DATA_RATE_400KHZ = 400000,
121     CYHAL_EZI2C_DATA_RATE_1MHZ   = 1000000
122 } cyhal_ezi2c_data_rate_t;
123 
124 /** Return codes of ezi2c */
125 typedef enum
126 {
127     /** Each EZI2C slave status is encoded in a separate bit, therefore multiple bits may be set to indicate the current status */
128     CYHAL_EZI2C_STATUS_OK     = 0x1UL,   /**< Operation completed successfully */
129     CYHAL_EZI2C_STATUS_READ1  = 0x2UL,  /**< The Read transfer intended for the primary slave address is complete */
130     CYHAL_EZI2C_STATUS_WRITE1 = 0x4UL,  /**< The Write transfer intended for the primary slave address is complete */
131     CYHAL_EZI2C_STATUS_READ2  = 0x8UL,  /**< The Read transfer intended for the secondary slave address is complete */
132     CYHAL_EZI2C_STATUS_WRITE2 = 0x10UL,  /**< The Write transfer intended for the secondary slave address is complete */
133     CYHAL_EZI2C_STATUS_BUSY   = 0x20UL,  /**< A transfer intended for the primary address or secondary address is in progress */
134     CYHAL_EZI2C_STATUS_ERR    = 0x40UL   /**< An error occurred during a transfer intended for the primary or secondary slave address */
135 
136 } cyhal_ezi2c_status_t;
137 
138 /** This type is deprecated and that cyhal_ezi2c_status_t should be used instead */
139 typedef cyhal_ezi2c_status_t cyhal_ezi2c_event_t;
140 
141 /** Handler for I2C events */
142 typedef void (*cyhal_ezi2c_event_callback_t)(void *callback_arg, cyhal_ezi2c_status_t event);
143 
144 /** Initial EZI2C sub configuration */
145 typedef struct
146 {
147     /** The 7-bit right justified primary slave address */
148     uint8_t slave_address;
149     /** A pointer to the data buffer for the primary/secondary slave address */
150     uint8_t *buf;
151     /** The size of the buffer assigned to the primary/secondary slave address */
152     uint32_t buf_size;
153     /** The Read/Write boundary within the buffer assigned to the primary/secondary slave address.
154     * This specifies the number of data bytes from the beginning of the buffer with
155     * read and write access for the master. Data bytes at this value or greater are read
156     * only by the master */
157     uint32_t buf_rw_boundary;
158 } cyhal_ezi2c_slave_cfg_t;
159 
160 /** Initial EZI2C configuration */
161 typedef struct
162 {
163     /** Number of addresses (one or two). If set "true" - use two addresses otherwise ("false") one */
164     bool two_addresses;
165     /** When set, the slave will wake the device from Deep Sleep on an address match */
166     bool enable_wake_from_sleep;
167     /** Maximum frequency that the I2C Slave bus runs at. Supports standard data rates of 100/400/1000 kbps */
168     cyhal_ezi2c_data_rate_t data_rate;
169     /** Refer to cyhal_ezi2c_slave_cfg_t for details. This config structure is mandatory. */
170     cyhal_ezi2c_slave_cfg_t slave1_cfg;
171     /** Refer to cyhal_ezi2c_slave_cfg_t for details. This config structure is optional. */
172     /** Set it if user want to use dual-port addressing otherwise leave blank */
173     cyhal_ezi2c_slave_cfg_t slave2_cfg;
174     /** The size of the sub-address, can either be 8 or 16 bits */
175     cyhal_ezi2c_sub_addr_size_t sub_address_size;
176 } cyhal_ezi2c_cfg_t;
177 
178 
179 /** Initialize the EZI2C (slave), and configures its specified pins and clock.
180  * See \ref subsection_ezi2c_snippet_1
181  *
182  * @param[out] obj  Pointer to an EZI2C object. The caller must allocate the memory
183  *  for this object but the init function will initialize its contents.
184  * @param[in]  sda The sda pin
185  * @param[in]  scl The scl pin
186  * @param[in]  clk The clock to use can be shared, if NULL a new clock will be allocated
187  * @param[in]  cfg The ezi2c configuration (refer to cyhal_ezi2c_cfg_t for details)
188  * @return The status of the init request
189  */
190 cy_rslt_t cyhal_ezi2c_init(cyhal_ezi2c_t *obj, cyhal_gpio_t sda, cyhal_gpio_t scl, const cyhal_clock_t *clk, const cyhal_ezi2c_cfg_t *cfg);
191 
192 /** Deinitialize the ezi2c object
193  *
194  * @param[in,out] obj The ezi2c object
195  */
196 void cyhal_ezi2c_free(cyhal_ezi2c_t *obj);
197 
198 /**
199  * EZI2C slave get activity status
200  * This function returns a non-zero value ( \ref cyhal_ezi2c_status_t) if an I2C Read or Write
201  * cycle has occurred since the last time this function was called.
202  * See \ref subsection_ezi2c_snippet_2
203  *
204  * @param[in] obj The EZI2C object
205  *
206  * @return The status of the EZI2C (see cyhal_ezi2c_status_t for details)
207  */
208 cyhal_ezi2c_status_t cyhal_ezi2c_get_activity_status(cyhal_ezi2c_t *obj);
209 
210 /** Register a EZI2C event callback handler
211  *
212  * See \ref subsection_ezi2c_snippet_2
213  *
214  * @param[in] obj          The EZI2C object
215  * @param[in] callback     The callback handler which will be invoked when an event triggers
216  * @param[in] callback_arg Generic argument that will be provided to the callback when called
217  */
218 void cyhal_ezi2c_register_callback(cyhal_ezi2c_t *obj, cyhal_ezi2c_event_callback_t callback, void *callback_arg);
219 
220 /** Configure and Enable or Disable EZI2C Interrupt.
221  *
222  * @param[in] obj            The EZI2C object
223  * @param[in] event          The EZI2C event type
224  * @param[in] intr_priority  The priority for NVIC interrupt events
225  * @param[in] enable         True to turn on interrupts, False to turn off
226  */
227 void cyhal_ezi2c_enable_event(cyhal_ezi2c_t *obj, cyhal_ezi2c_status_t event, uint8_t intr_priority, bool enable);
228 
229 /** Initialize the EZI2C peripheral using a configurator generated configuration struct and set up slave address(es) data.
230  *
231  * @param[in] obj            The EZI2C peripheral to configure
232  * @param[in] cfg            Configuration structure generated by a configurator.
233  * @param[in] slave1_cfg     Primary slave address configuration
234  * @param[in] slave2_cfg     Secondary slave address configuration (can be NULL)
235  * @return The status of the operation
236  */
237 cy_rslt_t cyhal_ezi2c_init_cfg(cyhal_ezi2c_t *obj, const cyhal_ezi2c_configurator_t *cfg, const cyhal_ezi2c_slave_cfg_t *slave1_cfg, const cyhal_ezi2c_slave_cfg_t *slave2_cfg);
238 
239 #if defined(__cplusplus)
240 }
241 #endif
242 
243 /** \} group_hal_ezi2c */
244