ESPHome  2024.3.1
remote_receiver_esp32.cpp
Go to the documentation of this file.
1 #include "remote_receiver.h"
2 #include "esphome/core/log.h"
3 
4 #ifdef USE_ESP32
5 #include <driver/rmt.h>
6 
7 namespace esphome {
8 namespace remote_receiver {
9 
10 static const char *const TAG = "remote_receiver.esp32";
11 
13  ESP_LOGCONFIG(TAG, "Setting up Remote Receiver...");
14  this->pin_->setup();
15  rmt_config_t rmt{};
16  this->config_rmt(rmt);
17  rmt.gpio_num = gpio_num_t(this->pin_->get_pin());
18  rmt.rmt_mode = RMT_MODE_RX;
19  if (this->filter_us_ == 0) {
20  rmt.rx_config.filter_en = false;
21  } else {
22  rmt.rx_config.filter_en = true;
23  rmt.rx_config.filter_ticks_thresh = this->from_microseconds_(this->filter_us_);
24  }
25  rmt.rx_config.idle_threshold = this->from_microseconds_(this->idle_us_);
26 
27  esp_err_t error = rmt_config(&rmt);
28  if (error != ESP_OK) {
29  this->error_code_ = error;
30  this->mark_failed();
31  return;
32  }
33 
34  error = rmt_driver_install(this->channel_, this->buffer_size_, 0);
35  if (error != ESP_OK) {
36  this->error_code_ = error;
37  this->mark_failed();
38  return;
39  }
40  error = rmt_get_ringbuf_handle(this->channel_, &this->ringbuf_);
41  if (error != ESP_OK) {
42  this->error_code_ = error;
43  this->mark_failed();
44  return;
45  }
46  error = rmt_rx_start(this->channel_, true);
47  if (error != ESP_OK) {
48  this->error_code_ = error;
49  this->mark_failed();
50  return;
51  }
52 }
54  ESP_LOGCONFIG(TAG, "Remote Receiver:");
55  LOG_PIN(" Pin: ", this->pin_);
56  if (this->pin_->digital_read()) {
57  ESP_LOGW(TAG, "Remote Receiver Signal starts with a HIGH value. Usually this means you have to "
58  "invert the signal using 'inverted: True' in the pin schema!");
59  }
60  ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_);
61  ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_);
62  ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_);
63  ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_);
64  ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_);
65  ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_);
66  if (this->is_failed()) {
67  ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_));
68  }
69 }
70 
72  size_t len = 0;
73  auto *item = (rmt_item32_t *) xRingbufferReceive(this->ringbuf_, &len, 0);
74  if (item != nullptr) {
75  this->decode_rmt_(item, len);
76  vRingbufferReturnItem(this->ringbuf_, item);
77 
78  if (this->temp_.empty())
79  return;
80 
81  this->temp_.push_back(-this->idle_us_);
83  }
84 }
85 void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) {
86  bool prev_level = false;
87  uint32_t prev_length = 0;
88  this->temp_.clear();
89  int32_t multiplier = this->pin_->is_inverted() ? -1 : 1;
90  size_t item_count = len / sizeof(rmt_item32_t);
91 
92  ESP_LOGVV(TAG, "START:");
93  for (size_t i = 0; i < item_count; i++) {
94  if (item[i].level0) {
95  ESP_LOGVV(TAG, "%zu A: ON %" PRIu32 "us (%u ticks)", i, this->to_microseconds_(item[i].duration0),
96  item[i].duration0);
97  } else {
98  ESP_LOGVV(TAG, "%zu A: OFF %" PRIu32 "us (%u ticks)", i, this->to_microseconds_(item[i].duration0),
99  item[i].duration0);
100  }
101  if (item[i].level1) {
102  ESP_LOGVV(TAG, "%zu B: ON %" PRIu32 "us (%u ticks)", i, this->to_microseconds_(item[i].duration1),
103  item[i].duration1);
104  } else {
105  ESP_LOGVV(TAG, "%zu B: OFF %" PRIu32 "us (%u ticks)", i, this->to_microseconds_(item[i].duration1),
106  item[i].duration1);
107  }
108  }
109  ESP_LOGVV(TAG, "\n");
110 
111  this->temp_.reserve(item_count * 2); // each RMT item has 2 pulses
112  for (size_t i = 0; i < item_count; i++) {
113  if (item[i].duration0 == 0u) {
114  // Do nothing
115  } else if (bool(item[i].level0) == prev_level) {
116  prev_length += item[i].duration0;
117  } else {
118  if (prev_length > 0) {
119  if (prev_level) {
120  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
121  } else {
122  this->temp_.push_back(-int32_t(this->to_microseconds_(prev_length)) * multiplier);
123  }
124  }
125  prev_level = bool(item[i].level0);
126  prev_length = item[i].duration0;
127  }
128 
129  if (item[i].duration1 == 0u) {
130  // Do nothing
131  } else if (bool(item[i].level1) == prev_level) {
132  prev_length += item[i].duration1;
133  } else {
134  if (prev_length > 0) {
135  if (prev_level) {
136  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
137  } else {
138  this->temp_.push_back(-int32_t(this->to_microseconds_(prev_length)) * multiplier);
139  }
140  }
141  prev_level = bool(item[i].level1);
142  prev_length = item[i].duration1;
143  }
144  }
145  if (prev_length > 0) {
146  if (prev_level) {
147  this->temp_.push_back(this->to_microseconds_(prev_length) * multiplier);
148  } else {
149  this->temp_.push_back(-int32_t(this->to_microseconds_(prev_length)) * multiplier);
150  }
151  }
152 }
153 
154 } // namespace remote_receiver
155 } // namespace esphome
156 
157 #endif
virtual void setup()=0
virtual uint8_t get_pin() const =0
virtual bool digital_read()=0
std::string size_t len
Definition: helpers.h:292
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
void decode_rmt_(rmt_item32_t *item, size_t len)
virtual bool is_inverted() const =0