1 /*
2  * SPDX-FileCopyrightText: 2010-2022 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 "soc/soc_caps.h"
11 #include "soc/clk_tree_defs.h"
12 #include "driver/gpio.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 
19 #define RMT_CHANNEL_FLAGS_AWARE_DFS (1 << 0) /*!< Channel can work during APB clock scaling */
20 #define RMT_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /*!< Invert RMT signal */
21 
22 /**
23  * @brief Define memory space of each RMT channel (in words = 4 bytes)
24  */
25 #define RMT_MEM_ITEM_NUM SOC_RMT_MEM_WORDS_PER_CHANNEL
26 
27 /**
28  * @brief Definition of RMT item
29  */
30 typedef struct {
31     union {
32         struct {
33             uint32_t duration0 : 15; /*!< Duration of level0 */
34             uint32_t level0 : 1;     /*!< Level of the first part */
35             uint32_t duration1 : 15; /*!< Duration of level1 */
36             uint32_t level1 : 1;     /*!< Level of the second part */
37         };
38         uint32_t val; /*!< Equivalent unsigned value for the RMT item */
39     };
40 } rmt_item32_t;
41 
42 
43 #if SOC_RMT_SUPPORTED
44 /**
45  * @brief RMT hardware memory layout
46  */
47 typedef struct {
48     struct {
49         volatile rmt_item32_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
50     } chan[SOC_RMT_CHANNELS_PER_GROUP];
51 } rmt_mem_t;
52 #endif // SOC_RMT_SUPPORTED
53 
54 /**
55  * @brief RMT channel ID
56  */
57 typedef enum {
58     RMT_CHANNEL_0,  /*!< RMT channel number 0 */
59     RMT_CHANNEL_1,  /*!< RMT channel number 1 */
60     RMT_CHANNEL_2,  /*!< RMT channel number 2 */
61     RMT_CHANNEL_3,  /*!< RMT channel number 3 */
62 #if SOC_RMT_CHANNELS_PER_GROUP > 4
63     RMT_CHANNEL_4,  /*!< RMT channel number 4 */
64     RMT_CHANNEL_5,  /*!< RMT channel number 5 */
65     RMT_CHANNEL_6,  /*!< RMT channel number 6 */
66     RMT_CHANNEL_7,  /*!< RMT channel number 7 */
67 #endif
68     RMT_CHANNEL_MAX /*!< Number of RMT channels */
69 } rmt_channel_t;
70 
71 /**
72  * @brief RMT Internal Memory Owner
73  */
74 typedef enum {
75     RMT_MEM_OWNER_TX, /*!< RMT RX mode, RMT transmitter owns the memory block*/
76     RMT_MEM_OWNER_RX, /*!< RMT RX mode, RMT receiver owns the memory block*/
77     RMT_MEM_OWNER_MAX,
78 } rmt_mem_owner_t;
79 
80 /**
81  * @brief Clock Source of RMT Channel
82  */
83 #if SOC_RMT_SUPPORTED
84 typedef soc_periph_rmt_clk_src_legacy_t rmt_source_clk_t;
85 #else
86 typedef int rmt_source_clk_t;
87 #endif // SOC_RMT_SUPPORTED
88 
89 /**
90  * @brief RMT Data Mode
91  *
92  * @note We highly recommended to use MEM mode not FIFO mode since there will be some gotcha in FIFO mode.
93  */
94 typedef enum {
95     RMT_DATA_MODE_FIFO, /*<! RMT memory access in FIFO mode */
96     RMT_DATA_MODE_MEM,  /*<! RMT memory access in memory mode */
97     RMT_DATA_MODE_MAX,
98 } rmt_data_mode_t;
99 
100 /**
101  * @brief RMT Channel Working Mode (TX or RX)
102  */
103 typedef enum {
104     RMT_MODE_TX, /*!< RMT TX mode */
105     RMT_MODE_RX, /*!< RMT RX mode */
106     RMT_MODE_MAX
107 } rmt_mode_t;
108 
109 /**
110  * @brief RMT Idle Level
111  *
112  */
113 typedef enum {
114     RMT_IDLE_LEVEL_LOW,  /*!< RMT TX idle level: low Level */
115     RMT_IDLE_LEVEL_HIGH, /*!< RMT TX idle level: high Level */
116     RMT_IDLE_LEVEL_MAX,
117 } rmt_idle_level_t;
118 
119 /**
120  * @brief RMT Carrier Level
121  */
122 typedef enum {
123     RMT_CARRIER_LEVEL_LOW,  /*!< RMT carrier wave is modulated for low Level output */
124     RMT_CARRIER_LEVEL_HIGH, /*!< RMT carrier wave is modulated for high Level output */
125     RMT_CARRIER_LEVEL_MAX
126 } rmt_carrier_level_t;
127 
128 /**
129  * @brief RMT Channel Status
130  */
131 typedef enum {
132     RMT_CHANNEL_UNINIT, /*!< RMT channel uninitialized */
133     RMT_CHANNEL_IDLE,   /*!< RMT channel status idle */
134     RMT_CHANNEL_BUSY,   /*!< RMT channel status busy */
135 } rmt_channel_status_t;
136 
137 /**
138  * @brief Data struct of RMT channel status
139  */
140 typedef struct {
141     rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */
142 } rmt_channel_status_result_t;
143 
144 /**
145  * @brief Data struct of RMT TX configure parameters
146  */
147 typedef struct {
148     uint32_t carrier_freq_hz;          /*!< RMT carrier frequency */
149     rmt_carrier_level_t carrier_level; /*!< Level of the RMT output, when the carrier is applied */
150     rmt_idle_level_t idle_level;       /*!< RMT idle level */
151     uint8_t carrier_duty_percent;      /*!< RMT carrier duty (%) */
152     uint32_t loop_count;               /*!< Maximum loop count, only take effect for chips that is capable of `SOC_RMT_SUPPORT_TX_LOOP_COUNT` */
153     bool carrier_en;                   /*!< RMT carrier enable */
154     bool loop_en;                      /*!< Enable sending RMT items in a loop */
155     bool idle_output_en;               /*!< RMT idle level output enable */
156 } rmt_tx_config_t;
157 
158 /**
159  * @brief Data struct of RMT RX configure parameters
160  */
161 typedef struct {
162     uint16_t idle_threshold;     /*!< RMT RX idle threshold */
163     uint8_t filter_ticks_thresh; /*!< RMT filter tick number */
164     bool filter_en;              /*!< RMT receiver filter enable */
165 #if SOC_RMT_SUPPORT_RX_DEMODULATION
166     bool rm_carrier;                   /*!< RMT receiver remove carrier enable */
167     uint32_t carrier_freq_hz;          /*!< RMT carrier frequency */
168     uint8_t carrier_duty_percent;      /*!< RMT carrier duty (%) */
169     rmt_carrier_level_t carrier_level; /*!< The level to remove the carrier */
170 #endif
171 } rmt_rx_config_t;
172 
173 /**
174  * @brief Data struct of RMT configure parameters
175  */
176 typedef struct {
177     rmt_mode_t rmt_mode;   /*!< RMT mode: transmitter or receiver */
178     rmt_channel_t channel; /*!< RMT channel */
179     gpio_num_t gpio_num;   /*!< RMT GPIO number */
180     uint8_t clk_div;       /*!< RMT channel counter divider */
181     uint8_t mem_block_num; /*!< RMT memory block number */
182     uint32_t flags;        /*!< RMT channel extra configurations, OR'd with RMT_CHANNEL_FLAGS_[*] */
183     union {
184         rmt_tx_config_t tx_config; /*!< RMT TX parameter */
185         rmt_rx_config_t rx_config; /*!< RMT RX parameter */
186     };
187 } rmt_config_t;
188 
189 #if CONFIG_IDF_TARGET_ESP32H2
190 #define RMT_DEFAULT_CLK_DIV 32
191 #else
192 #define RMT_DEFAULT_CLK_DIV 80
193 #endif
194 
195 /**
196  * @brief Default configuration for Tx channel
197  *
198  */
199 #define RMT_DEFAULT_CONFIG_TX(gpio, channel_id)      \
200     {                                                \
201         .rmt_mode = RMT_MODE_TX,                     \
202         .channel = channel_id,                       \
203         .gpio_num = gpio,                            \
204         .clk_div = RMT_DEFAULT_CLK_DIV,              \
205         .mem_block_num = 1,                          \
206         .flags = 0,                                  \
207         .tx_config = {                               \
208             .carrier_freq_hz = 38000,                \
209             .carrier_level = RMT_CARRIER_LEVEL_HIGH, \
210             .idle_level = RMT_IDLE_LEVEL_LOW,        \
211             .carrier_duty_percent = 33,              \
212             .loop_count = 0,                         \
213             .carrier_en = false,                     \
214             .loop_en = false,                        \
215             .idle_output_en = true,                  \
216         }                                            \
217     }
218 
219 /**
220  * @brief Default configuration for RX channel
221  *
222  */
223 #define RMT_DEFAULT_CONFIG_RX(gpio, channel_id) \
224     {                                           \
225         .rmt_mode = RMT_MODE_RX,                \
226         .channel = channel_id,                  \
227         .gpio_num = gpio,                       \
228         .clk_div = RMT_DEFAULT_CLK_DIV,         \
229         .mem_block_num = 1,                     \
230         .flags = 0,                             \
231         .rx_config = {                          \
232             .idle_threshold = 12000,            \
233             .filter_ticks_thresh = 100,         \
234             .filter_en = true,                  \
235         }                                       \
236     }
237 
238 /**
239  * @brief RMT interrupt handle
240  */
241 typedef intr_handle_t rmt_isr_handle_t;
242 
243 /**
244  * @brief Type of RMT Tx End callback function
245  */
246 typedef void (*rmt_tx_end_fn_t)(rmt_channel_t channel, void *arg);
247 
248 /**
249  * @brief Structure encapsulating a RMT TX end callback
250  */
251 typedef struct {
252     rmt_tx_end_fn_t function; /*!< Function which is called on RMT TX end */
253     void *arg;                /*!< Optional argument passed to function */
254 } rmt_tx_end_callback_t;
255 
256 /**
257  * @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t).
258  *
259  *        This function may be called from an ISR, so, the code should be short and efficient.
260  *
261  * @param  src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
262  * @param[out] dest Pointer to the buffer storing the rmt format data.
263  * @param  src_size The raw data size.
264  * @param  wanted_num The number of rmt format data that wanted to get.
265  * @param[out] translated_size The size of the raw data that has been converted to rmt format,
266  *             it should return 0 if no data is converted in user callback.
267  * @param[out] item_num The number of the rmt format data that actually converted to,
268  *             it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
269  *             it should return 0 if no data was converted.
270  *
271  * @note
272  *       In fact, item_num should be a multiple of translated_size, e.g. :
273  *       When we convert each byte of uint8_t type data to rmt format data,
274  *       the relation between item_num and translated_size should be `item_num = translated_size*8`.
275  */
276 typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
277 
278 #ifdef __cplusplus
279 }
280 #endif
281