1
6
7
14
15
16
17
18
19
20
23
24
25
26
27
28
29
30
31
32
33
34
37
38
39
40
43
48
49
52
57
58
61
66
67
70
71
72
73
74
75
76
77
80
81
91
101
102
103
104
105
106
107
110
115
116
119
120
121
122
126
127
128
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
163
164
165
166
167
168
169
172
173
174
175
179
180
181
188
189
190
191
192
196
197
198
199
202
203
204
207
208
209
210
211
212
213
214
215
216
217
218
219
235
/* ... */
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "driver/rmt_tx.h"
#include "driver/rmt_rx.h"
#include "ir_nec_encoder.h"7 includes
#define EXAMPLE_IR_RESOLUTION_HZ 1000000
#define EXAMPLE_IR_TX_GPIO_NUM 18
#define EXAMPLE_IR_RX_GPIO_NUM 19
#define EXAMPLE_IR_NEC_DECODE_MARGIN 200
/* ... */
#define NEC_LEADING_CODE_DURATION_0 9000
#define NEC_LEADING_CODE_DURATION_1 4500
#define NEC_PAYLOAD_ZERO_DURATION_0 560
#define NEC_PAYLOAD_ZERO_DURATION_1 560
#define NEC_PAYLOAD_ONE_DURATION_0 560
#define NEC_PAYLOAD_ONE_DURATION_1 1690
#define NEC_REPEAT_CODE_DURATION_0 9000
#define NEC_REPEAT_CODE_DURATION_1 225012 defines
static const char *TAG = "example";
/* ... */
static uint16_t s_nec_code_address;
static uint16_t s_nec_code_command;
/* ... */
static inline bool nec_check_in_range(uint32_t signal_duration, uint32_t spec_duration)
{
return (signal_duration < (spec_duration + EXAMPLE_IR_NEC_DECODE_MARGIN)) &&
(signal_duration > (spec_duration - EXAMPLE_IR_NEC_DECODE_MARGIN));
}{ ... }
/* ... */
static bool nec_parse_logic0(rmt_symbol_word_t *rmt_nec_symbols)
{
return nec_check_in_range(rmt_nec_symbols->duration0, NEC_PAYLOAD_ZERO_DURATION_0) &&
nec_check_in_range(rmt_nec_symbols->duration1, NEC_PAYLOAD_ZERO_DURATION_1);
}{ ... }
/* ... */
static bool nec_parse_logic1(rmt_symbol_word_t *rmt_nec_symbols)
{
return nec_check_in_range(rmt_nec_symbols->duration0, NEC_PAYLOAD_ONE_DURATION_0) &&
nec_check_in_range(rmt_nec_symbols->duration1, NEC_PAYLOAD_ONE_DURATION_1);
}{ ... }
/* ... */
static bool nec_parse_frame(rmt_symbol_word_t *rmt_nec_symbols)
{
rmt_symbol_word_t *cur = rmt_nec_symbols;
uint16_t address = 0;
uint16_t command = 0;
bool valid_leading_code = nec_check_in_range(cur->duration0, NEC_LEADING_CODE_DURATION_0) &&
nec_check_in_range(cur->duration1, NEC_LEADING_CODE_DURATION_1);
if (!valid_leading_code) {
return false;
}{...}
cur++;
for (int i = 0; i < 16; i++) {
if (nec_parse_logic1(cur)) {
address |= 1 << i;
}{...} else if (nec_parse_logic0(cur)) {
address &= ~(1 << i);
}{...} else {
return false;
}{...}
cur++;
}{...}
for (int i = 0; i < 16; i++) {
if (nec_parse_logic1(cur)) {
command |= 1 << i;
}{...} else if (nec_parse_logic0(cur)) {
command &= ~(1 << i);
}{...} else {
return false;
}{...}
cur++;
}{...}
s_nec_code_address = address;
s_nec_code_command = command;
return true;
}{ ... }
/* ... */
static bool nec_parse_frame_repeat(rmt_symbol_word_t *rmt_nec_symbols)
{
return nec_check_in_range(rmt_nec_symbols->duration0, NEC_REPEAT_CODE_DURATION_0) &&
nec_check_in_range(rmt_nec_symbols->duration1, NEC_REPEAT_CODE_DURATION_1);
}{ ... }
/* ... */
static void example_parse_nec_frame(rmt_symbol_word_t *rmt_nec_symbols, size_t symbol_num)
{
printf("NEC frame start---\r\n");
for (size_t i = 0; i < symbol_num; i++) {
printf("{%d:%d},{%d:%d}\r\n", rmt_nec_symbols[i].level0, rmt_nec_symbols[i].duration0,
rmt_nec_symbols[i].level1, rmt_nec_symbols[i].duration1);
}{...}
printf("---NEC frame end: ");
switch (symbol_num) {
case 34:
if (nec_parse_frame(rmt_nec_symbols)) {
printf("Address=%04X, Command=%04X\r\n\r\n", s_nec_code_address, s_nec_code_command);
}{...}
break;...
case 2:
if (nec_parse_frame_repeat(rmt_nec_symbols)) {
printf("Address=%04X, Command=%04X, repeat\r\n\r\n", s_nec_code_address, s_nec_code_command);
}{...}
break;...
default:
printf("Unknown NEC frame\r\n\r\n");
break;...
}{...}
}{ ... }
static bool example_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
{
BaseType_t high_task_wakeup = pdFALSE;
QueueHandle_t receive_queue = (QueueHandle_t)user_data;
xQueueSendFromISR(receive_queue, edata, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}{ ... }
void app_main(void)
{
ESP_LOGI(TAG, "create RMT RX channel");
rmt_rx_channel_config_t rx_channel_cfg = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = EXAMPLE_IR_RESOLUTION_HZ,
.mem_block_symbols = 64,
.gpio_num = EXAMPLE_IR_RX_GPIO_NUM,
}{...};
rmt_channel_handle_t rx_channel = NULL;
ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_channel_cfg, &rx_channel));
ESP_LOGI(TAG, "register RX done callback");
QueueHandle_t receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t));
assert(receive_queue);
rmt_rx_event_callbacks_t cbs = {
.on_recv_done = example_rmt_rx_done_callback,
}{...};
ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(rx_channel, &cbs, receive_queue));
rmt_receive_config_t receive_config = {
.signal_range_min_ns = 1250,
.signal_range_max_ns = 12000000,
}{...};
ESP_LOGI(TAG, "create RMT TX channel");
rmt_tx_channel_config_t tx_channel_cfg = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = EXAMPLE_IR_RESOLUTION_HZ,
.mem_block_symbols = 64,
.trans_queue_depth = 4,
.gpio_num = EXAMPLE_IR_TX_GPIO_NUM,
}{...};
rmt_channel_handle_t tx_channel = NULL;
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_channel_cfg, &tx_channel));
ESP_LOGI(TAG, "modulate carrier to TX channel");
rmt_carrier_config_t carrier_cfg = {
.duty_cycle = 0.33,
.frequency_hz = 38000,
}{...};
ESP_ERROR_CHECK(rmt_apply_carrier(tx_channel, &carrier_cfg));
rmt_transmit_config_t transmit_config = {
.loop_count = 0,
}{...};
ESP_LOGI(TAG, "install IR NEC encoder");
ir_nec_encoder_config_t nec_encoder_cfg = {
.resolution = EXAMPLE_IR_RESOLUTION_HZ,
}{...};
rmt_encoder_handle_t nec_encoder = NULL;
ESP_ERROR_CHECK(rmt_new_ir_nec_encoder(&nec_encoder_cfg, &nec_encoder));
ESP_LOGI(TAG, "enable RMT TX and RX channels");
ESP_ERROR_CHECK(rmt_enable(tx_channel));
ESP_ERROR_CHECK(rmt_enable(rx_channel));
rmt_symbol_word_t raw_symbols[64];
rmt_rx_done_event_data_t rx_data;
ESP_ERROR_CHECK(rmt_receive(rx_channel, raw_symbols, sizeof(raw_symbols), &receive_config));
while (1) {
if (xQueueReceive(receive_queue, &rx_data, pdMS_TO_TICKS(1000)) == pdPASS) {
example_parse_nec_frame(rx_data.received_symbols, rx_data.num_symbols);
ESP_ERROR_CHECK(rmt_receive(rx_channel, raw_symbols, sizeof(raw_symbols), &receive_config));
}{...} else {
const ir_nec_scan_code_t scan_code = {
.address = 0x0440,
.command = 0x3003,
}{...};
ESP_ERROR_CHECK(rmt_transmit(tx_channel, nec_encoder, &scan_code, sizeof(scan_code), &transmit_config));
}{...}
}{...}
}{ ... }