1 /*
2  * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include "esp_err.h"
12 #include "esp_attr.h"
13 #include "soc/soc_caps.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @brief Type of Dedicated GPIO bundle
21  */
22 typedef struct dedic_gpio_bundle_t *dedic_gpio_bundle_handle_t;
23 
24 /**
25  * @brief Type of Dedicated GPIO bundle configuration
26  */
27 typedef struct {
28     const int *gpio_array; /*!< Array of GPIO numbers, gpio_array[0] ~ gpio_array[size-1] <=> low_dedic_channel_num ~ high_dedic_channel_num */
29     size_t array_size;     /*!< Number of GPIOs in gpio_array */
30     struct {
31         unsigned int in_en: 1;      /*!< Enable input */
32         unsigned int in_invert: 1;  /*!< Invert input signal */
33         unsigned int out_en: 1;     /*!< Enable output */
34         unsigned int out_invert: 1; /*!< Invert output signal */
35     } flags; /*!< Flags to control specific behaviour of GPIO bundle */
36 } dedic_gpio_bundle_config_t;
37 
38 /**
39  * @brief Create GPIO bundle and return the handle
40  *
41  * @param[in] config Configuration of GPIO bundle
42  * @param[out] ret_bundle Returned handle of the new created GPIO bundle
43  * @return
44  *      - ESP_OK: Create GPIO bundle successfully
45  *      - ESP_ERR_INVALID_ARG: Create GPIO bundle failed because of invalid argument
46  *      - ESP_ERR_NO_MEM: Create GPIO bundle failed because of no capable memory
47  *      - ESP_ERR_NOT_FOUND: Create GPIO bundle failed because of no enough continuous dedicated channels
48  *      - ESP_FAIL: Create GPIO bundle failed because of other error
49  *
50  * @note One has to enable at least input or output mode in "config" parameter.
51  */
52 esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_gpio_bundle_handle_t *ret_bundle);
53 
54 /**
55  * @brief Destroy GPIO bundle
56  *
57  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
58  * @return
59  *      - ESP_OK: Destroy GPIO bundle successfully
60  *      - ESP_ERR_INVALID_ARG: Destroy GPIO bundle failed because of invalid argument
61  *      - ESP_FAIL: Destroy GPIO bundle failed because of other error
62  */
63 esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle);
64 
65 /**@{*/
66 /**
67  * @brief Get allocated channel mask
68  *
69  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
70  * @param[out] mask Returned mask value for on specific direction (in or out)
71  * @return
72  *      - ESP_OK: Get channel mask successfully
73  *      - ESP_ERR_INVALID_ARG: Get channel mask failed because of invalid argument
74  *      - ESP_FAIL: Get channel mask failed because of other error
75  *
76  * @note Each bundle should have at least one mask (in or/and out), based on bundle configuration.
77  * @note With the returned mask, user can directly invoke LL function like "dedic_gpio_cpu_ll_write_mask"
78  *       or write assembly code with dedicated GPIO instructions, to get better performance on GPIO manipulation.
79  */
80 esp_err_t dedic_gpio_get_out_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
81 esp_err_t dedic_gpio_get_in_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
82 /**@}*/
83 
84 /**@{*/
85 /**
86  * @brief Get the channel offset of the GPIO bundle
87  *
88  * A GPIO bundle maps the GPIOS of a particular direction to a consecutive set of channels within
89  * a particular GPIO bank of a particular CPU. This function returns the offset to
90  * the bundle's first channel of a particular direction within the bank.
91  *
92  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
93  * @param[out] offset Offset value to the first channel of a specific direction (in or out)
94  * @return
95  *      - ESP_OK: Get channel offset successfully
96  *      - ESP_ERR_INVALID_ARG: Get channel offset failed because of invalid argument
97  *      - ESP_FAIL: Get channel offset failed because of other error
98  */
99 esp_err_t dedic_gpio_get_out_offset(dedic_gpio_bundle_handle_t bundle, uint32_t *offset);
100 esp_err_t dedic_gpio_get_in_offset(dedic_gpio_bundle_handle_t bundle, uint32_t *offset);
101 /**@}*/
102 
103 /**
104  * @brief Write value to GPIO bundle
105  *
106  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
107  * @param[in] mask Mask of the GPIOs to be written in the given bundle
108  * @param[in] value Value to write to given GPIO bundle, low bit represents low member in the bundle
109  *
110  * @note The mask is seen from the view of GPIO bundle.
111  *       For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
112  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
113  */
114 void dedic_gpio_bundle_write(dedic_gpio_bundle_handle_t bundle, uint32_t mask, uint32_t value) IRAM_ATTR;
115 
116 /**
117  * @brief Read the value that output from the given GPIO bundle
118  *
119  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
120  * @return Value that output from the GPIO bundle, low bit represents low member in the bundle
121  *
122  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
123  */
124 uint32_t dedic_gpio_bundle_read_out(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
125 
126 /**
127  * @brief Read the value that input to the given GPIO bundle
128  *
129  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
130  * @return Value that input to the GPIO bundle, low bit represents low member in the bundle
131  *
132  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
133  */
134 uint32_t dedic_gpio_bundle_read_in(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
135 
136 #if SOC_DEDIC_GPIO_HAS_INTERRUPT
137 
138 /**
139  * @brief Supported type of dedicated GPIO interrupt
140  */
141 typedef enum {
142     DEDIC_GPIO_INTR_NONE,          /*!< No interrupt */
143     DEDIC_GPIO_INTR_LOW_LEVEL = 2, /*!< Interrupt on low level */
144     DEDIC_GPIO_INTR_HIGH_LEVEL,    /*!< Interrupt on high level */
145     DEDIC_GPIO_INTR_NEG_EDGE,      /*!< Interrupt on negedge */
146     DEDIC_GPIO_INTR_POS_EDGE,      /*!< Interrupt on posedge */
147     DEDIC_GPIO_INTR_BOTH_EDGE      /*!< Interrupt on both negedge and posedge */
148 } dedic_gpio_intr_type_t;
149 
150 /**
151  * @brief Type of dedicated GPIO ISR callback function
152  *
153  * @param bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
154  * @param index Index of the GPIO in its corresponding bundle (count from 0)
155  * @param args User defined arguments for the callback function. It's passed through `dedic_gpio_bundle_set_interrupt_and_callback`
156  * @return If a high priority task is woken up by the callback function
157  */
158 typedef bool (*dedic_gpio_isr_callback_t)(dedic_gpio_bundle_handle_t bundle, uint32_t index, void *args);
159 
160 /**
161  * @brief Set interrupt and callback function for GPIO bundle
162  *
163  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
164  * @param[in] mask Mask of the GPIOs in the given bundle
165  * @param[in] intr_type Interrupt type, set to DEDIC_GPIO_INTR_NONE can disable interrupt
166  * @param[in] cb_isr Callback function, which got invoked in ISR context. A NULL pointer here will bypass the callback
167  * @param[in] cb_args User defined argument to be passed to the callback function
168  *
169  * @note This function is only valid for bundle with input mode enabled. See "dedic_gpio_bundle_config_t"
170  * @note The mask is seen from the view of GPIO Bundle.
171  *       For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
172  *
173  * @return
174  *      - ESP_OK: Set GPIO interrupt and callback function successfully
175  *      - ESP_ERR_INVALID_ARG: Set GPIO interrupt and callback function failed because of invalid argument
176  *      - ESP_FAIL: Set GPIO interrupt and callback function failed because of other error
177  */
178 esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_t bundle, uint32_t mask, dedic_gpio_intr_type_t intr_type, dedic_gpio_isr_callback_t cb_isr, void *cb_args);
179 
180 #endif // SOC_DEDIC_GPIO_HAS_INTERRUPT
181 
182 #ifdef __cplusplus
183 }
184 #endif
185