ESPHome  2024.11.0
remote_base.cpp
Go to the documentation of this file.
1 #include "remote_base.h"
2 #include "esphome/core/log.h"
3 
4 #include <cinttypes>
5 
6 namespace esphome {
7 namespace remote_base {
8 
9 static const char *const TAG = "remote_base";
10 
11 #ifdef USE_ESP32
12 RemoteRMTChannel::RemoteRMTChannel(uint8_t mem_block_num) : mem_block_num_(mem_block_num) {
13  static rmt_channel_t next_rmt_channel = RMT_CHANNEL_0;
14  this->channel_ = next_rmt_channel;
15  next_rmt_channel = rmt_channel_t(int(next_rmt_channel) + mem_block_num);
16 }
17 
18 RemoteRMTChannel::RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num)
19  : channel_(channel), mem_block_num_(mem_block_num) {}
20 
21 void RemoteRMTChannel::config_rmt(rmt_config_t &rmt) {
22  if (rmt_channel_t(int(this->channel_) + this->mem_block_num_) > RMT_CHANNEL_MAX) {
23  this->mem_block_num_ = int(RMT_CHANNEL_MAX) - int(this->channel_);
24  ESP_LOGW(TAG, "Not enough RMT memory blocks available, reduced to %i blocks.", this->mem_block_num_);
25  }
26  rmt.channel = this->channel_;
27  rmt.clk_div = this->clock_divider_;
28  rmt.mem_block_num = this->mem_block_num_;
29 }
30 #endif
31 
32 /* RemoteReceiveData */
33 
34 bool RemoteReceiveData::peek_mark(uint32_t length, uint32_t offset) const {
35  if (!this->is_valid(offset))
36  return false;
37  const int32_t value = this->peek(offset);
38  const int32_t lo = this->lower_bound_(length);
39  const int32_t hi = this->upper_bound_(length);
40  return value >= 0 && lo <= value && value <= hi;
41 }
42 
43 bool RemoteReceiveData::peek_space(uint32_t length, uint32_t offset) const {
44  if (!this->is_valid(offset))
45  return false;
46  const int32_t value = this->peek(offset);
47  const int32_t lo = this->lower_bound_(length);
48  const int32_t hi = this->upper_bound_(length);
49  return value <= 0 && lo <= -value && -value <= hi;
50 }
51 
52 bool RemoteReceiveData::peek_space_at_least(uint32_t length, uint32_t offset) const {
53  if (!this->is_valid(offset))
54  return false;
55  const int32_t value = this->peek(offset);
56  const int32_t lo = this->lower_bound_(length);
57  return value <= 0 && lo <= -value;
58 }
59 
61  if (!this->peek_mark(length))
62  return false;
63  this->advance();
64  return true;
65 }
66 
68  if (!this->peek_space(length))
69  return false;
70  this->advance();
71  return true;
72 }
73 
74 bool RemoteReceiveData::expect_item(uint32_t mark, uint32_t space) {
75  if (!this->peek_item(mark, space))
76  return false;
77  this->advance(2);
78  return true;
79 }
80 
81 bool RemoteReceiveData::expect_pulse_with_gap(uint32_t mark, uint32_t space) {
82  if (!this->peek_space_at_least(space, 1) || !this->peek_mark(mark))
83  return false;
84  this->advance(2);
85  return true;
86 }
87 
88 /* RemoteReceiverBinarySensorBase */
89 
91  if (!this->matches(src))
92  return false;
93  this->publish_state(true);
94  yield();
95  this->publish_state(false);
96  return true;
97 }
98 
99 /* RemoteReceiverBase */
100 
102  if (dumper->is_secondary()) {
103  this->secondary_dumpers_.push_back(dumper);
104  } else {
105  this->dumpers_.push_back(dumper);
106  }
107 }
108 
110  for (auto *listener : this->listeners_)
111  listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
112 }
113 
115  bool success = false;
116  for (auto *dumper : this->dumpers_) {
117  if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
118  success = true;
119  }
120  if (!success) {
121  for (auto *dumper : this->secondary_dumpers_)
122  dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
123  }
124 }
125 
126 void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); }
127 
128 void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) {
129 #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
130  const auto &vec = this->temp_.get_data();
131  char buffer[256];
132  uint32_t buffer_offset = 0;
133  buffer_offset += sprintf(buffer, "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait);
134 
135  for (size_t i = 0; i < vec.size(); i++) {
136  const int32_t value = vec[i];
137  const uint32_t remaining_length = sizeof(buffer) - buffer_offset;
138  int written;
139 
140  if (i + 1 < vec.size()) {
141  written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32 ", ", value);
142  } else {
143  written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32, value);
144  }
145 
146  if (written < 0 || written >= int(remaining_length)) {
147  // write failed, flush...
148  buffer[buffer_offset] = '\0';
149  ESP_LOGVV(TAG, "%s", buffer);
150  buffer_offset = 0;
151  written = sprintf(buffer, " ");
152  if (i + 1 < vec.size()) {
153  written += sprintf(buffer + written, "%" PRId32 ", ", value);
154  } else {
155  written += sprintf(buffer + written, "%" PRId32, value);
156  }
157  }
158 
159  buffer_offset += written;
160  }
161  if (buffer_offset != 0) {
162  ESP_LOGVV(TAG, "%s", buffer);
163  }
164 #endif
165  this->send_internal(send_times, send_wait);
166 }
167 } // namespace remote_base
168 } // namespace esphome
void config_rmt(rmt_config_t &rmt)
Definition: remote_base.cpp:21
bool expect_pulse_with_gap(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:81
RemoteRMTChannel(uint8_t mem_block_num=1)
Definition: remote_base.cpp:12
bool peek_space(uint32_t length, uint32_t offset=0) const
Definition: remote_base.cpp:43
bool peek_mark(uint32_t length, uint32_t offset=0) const
Definition: remote_base.cpp:34
bool on_receive(RemoteReceiveData src) override
Definition: remote_base.cpp:90
void IRAM_ATTR HOT yield()
Definition: core.cpp:24
uint16_t length
Definition: tt21100.cpp:12
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void register_dumper(RemoteReceiverDumperBase *dumper)
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:74
void send_(uint32_t send_times, uint32_t send_wait)
bool peek_space_at_least(uint32_t length, uint32_t offset=0) const
Definition: remote_base.cpp:52