ESPHome  2024.4.0
remote_base.h
Go to the documentation of this file.
1 #include <utility>
2 #include <vector>
3 
4 #pragma once
5 
9 #include "esphome/core/hal.h"
10 
11 #ifdef USE_ESP32
12 #include <driver/rmt.h>
13 #endif
14 
15 namespace esphome {
16 namespace remote_base {
17 
18 using RawTimings = std::vector<int32_t>;
19 
21  public:
22  void mark(uint32_t length) { this->data_.push_back(length); }
23  void space(uint32_t length) { this->data_.push_back(-length); }
24  void item(uint32_t mark, uint32_t space) {
25  this->mark(mark);
26  this->space(space);
27  }
28  void reserve(uint32_t len) { this->data_.reserve(len); }
29  void set_carrier_frequency(uint32_t carrier_frequency) { this->carrier_frequency_ = carrier_frequency; }
30  uint32_t get_carrier_frequency() const { return this->carrier_frequency_; }
31  const RawTimings &get_data() const { return this->data_; }
32  void set_data(const RawTimings &data) { this->data_ = data; }
33  void reset() {
34  this->data_.clear();
35  this->carrier_frequency_ = 0;
36  }
37 
38  protected:
40  uint32_t carrier_frequency_{0};
41 };
42 
44  public:
45  explicit RemoteReceiveData(const RawTimings &data, uint8_t tolerance)
46  : data_(data), index_(0), tolerance_(tolerance) {}
47 
48  const RawTimings &get_raw_data() const { return this->data_; }
49  uint32_t get_index() const { return index_; }
50  int32_t operator[](uint32_t index) const { return this->data_[index]; }
51  int32_t size() const { return this->data_.size(); }
52  bool is_valid(uint32_t offset) const { return this->index_ + offset < this->data_.size(); }
53  int32_t peek(uint32_t offset = 0) const { return this->data_[this->index_ + offset]; }
54  bool peek_mark(uint32_t length, uint32_t offset = 0) const;
55  bool peek_space(uint32_t length, uint32_t offset = 0) const;
56  bool peek_space_at_least(uint32_t length, uint32_t offset = 0) const;
57  bool peek_item(uint32_t mark, uint32_t space, uint32_t offset = 0) const {
58  return this->peek_space(space, offset + 1) && this->peek_mark(mark, offset);
59  }
60 
61  bool expect_mark(uint32_t length);
62  bool expect_space(uint32_t length);
63  bool expect_item(uint32_t mark, uint32_t space);
64  bool expect_pulse_with_gap(uint32_t mark, uint32_t space);
65  void advance(uint32_t amount = 1) { this->index_ += amount; }
66  void reset() { this->index_ = 0; }
67 
68  protected:
69  int32_t lower_bound_(uint32_t length) const { return int32_t(100 - this->tolerance_) * length / 100U; }
70  int32_t upper_bound_(uint32_t length) const { return int32_t(100 + this->tolerance_) * length / 100U; }
71 
72  const RawTimings &data_;
73  uint32_t index_;
74  uint8_t tolerance_;
75 };
76 
78  public:
79  explicit RemoteComponentBase(InternalGPIOPin *pin) : pin_(pin){};
80 
81  protected:
82  InternalGPIOPin *pin_;
83 };
84 
85 #ifdef USE_ESP32
87  public:
88  explicit RemoteRMTChannel(uint8_t mem_block_num = 1);
89  explicit RemoteRMTChannel(rmt_channel_t channel, uint8_t mem_block_num = 1);
90 
91  void config_rmt(rmt_config_t &rmt);
92  void set_clock_divider(uint8_t clock_divider) { this->clock_divider_ = clock_divider; }
93 
94  protected:
95  uint32_t from_microseconds_(uint32_t us) {
96  const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
97  return us * ticks_per_ten_us / 10;
98  }
99  uint32_t to_microseconds_(uint32_t ticks) {
100  const uint32_t ticks_per_ten_us = 80000000u / this->clock_divider_ / 100000u;
101  return (ticks * 10) / ticks_per_ten_us;
102  }
104  rmt_channel_t channel_{RMT_CHANNEL_0};
105  uint8_t mem_block_num_;
106  uint8_t clock_divider_{80};
107 };
108 #endif
109 
111  public:
113  class TransmitCall {
114  public:
115  explicit TransmitCall(RemoteTransmitterBase *parent) : parent_(parent) {}
116  RemoteTransmitData *get_data() { return &this->parent_->temp_; }
117  void set_send_times(uint32_t send_times) { send_times_ = send_times; }
118  void set_send_wait(uint32_t send_wait) { send_wait_ = send_wait; }
119  void perform() { this->parent_->send_(this->send_times_, this->send_wait_); }
120 
121  protected:
123  uint32_t send_times_{1};
124  uint32_t send_wait_{0};
125  };
126 
128  this->temp_.reset();
129  return TransmitCall(this);
130  }
131  template<typename Protocol>
132  void transmit(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
133  auto call = this->transmit();
134  Protocol().encode(call.get_data(), data);
135  call.set_send_times(send_times);
136  call.set_send_wait(send_wait);
137  call.perform();
138  }
139 
140  protected:
141  void send_(uint32_t send_times, uint32_t send_wait);
142  virtual void send_internal(uint32_t send_times, uint32_t send_wait) = 0;
143  void send_single_() { this->send_(1, 0); }
144 
147 };
148 
150  public:
151  virtual bool on_receive(RemoteReceiveData data) = 0;
152 };
153 
155  public:
156  virtual bool dump(RemoteReceiveData src) = 0;
157  virtual bool is_secondary() { return false; }
158 };
159 
161  public:
163  void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
164  void register_dumper(RemoteReceiverDumperBase *dumper);
165  void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; }
166 
167  protected:
168  void call_listeners_();
169  void call_dumpers_();
171  this->call_listeners_();
172  this->call_dumpers_();
173  }
174 
175  std::vector<RemoteReceiverListener *> listeners_;
176  std::vector<RemoteReceiverDumperBase *> dumpers_;
177  std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
179  uint8_t tolerance_;
180 };
181 
183  public Component,
184  public RemoteReceiverListener {
185  public:
187  void dump_config() override;
188  virtual bool matches(RemoteReceiveData src) = 0;
189  bool on_receive(RemoteReceiveData src) override;
190 };
191 
192 /* TEMPLATES */
193 
194 template<typename T> class RemoteProtocol {
195  public:
196  using ProtocolData = T;
197  virtual void encode(RemoteTransmitData *dst, const ProtocolData &data) = 0;
198  virtual optional<ProtocolData> decode(RemoteReceiveData src) = 0;
199  virtual void dump(const ProtocolData &data) = 0;
200 };
201 
202 template<typename T> class RemoteReceiverBinarySensor : public RemoteReceiverBinarySensorBase {
203  public:
205 
206  protected:
207  bool matches(RemoteReceiveData src) override {
208  auto proto = T();
209  auto res = proto.decode(src);
210  return res.has_value() && *res == this->data_;
211  }
212 
213  public:
214  void set_data(typename T::ProtocolData data) { data_ = data; }
215 
216  protected:
217  typename T::ProtocolData data_;
218 };
219 
220 template<typename T>
221 class RemoteReceiverTrigger : public Trigger<typename T::ProtocolData>, public RemoteReceiverListener {
222  protected:
223  bool on_receive(RemoteReceiveData src) override {
224  auto proto = T();
225  auto res = proto.decode(src);
226  if (res.has_value()) {
227  this->trigger(*res);
228  return true;
229  }
230  return false;
231  }
232 };
233 
235  public:
237  RemoteTransmittable(RemoteTransmitterBase *transmitter) : transmitter_(transmitter) {}
238  void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_ = transmitter; }
239 
240  protected:
241  template<typename Protocol>
242  void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
243  this->transmitter_->transmit<Protocol>(data, send_times, send_wait);
244  }
246 };
247 
248 template<typename... Ts> class RemoteTransmitterActionBase : public RemoteTransmittable, public Action<Ts...> {
249  TEMPLATABLE_VALUE(uint32_t, send_times)
250  TEMPLATABLE_VALUE(uint32_t, send_wait)
251 
252  protected:
253  void play(Ts... x) override {
254  auto call = this->transmitter_->transmit();
255  this->encode(call.get_data(), x...);
256  call.set_send_times(this->send_times_.value_or(x..., 1));
257  call.set_send_wait(this->send_wait_.value_or(x..., 0));
258  call.perform();
259  }
260  virtual void encode(RemoteTransmitData *dst, Ts... x) = 0;
261 };
262 
263 template<typename T> class RemoteReceiverDumper : public RemoteReceiverDumperBase {
264  public:
265  bool dump(RemoteReceiveData src) override {
266  auto proto = T();
267  auto decoded = proto.decode(src);
268  if (!decoded.has_value())
269  return false;
270  proto.dump(*decoded);
271  return true;
272  }
273 };
274 
275 #define DECLARE_REMOTE_PROTOCOL_(prefix) \
276  using prefix##BinarySensor = RemoteReceiverBinarySensor<prefix##Protocol>; \
277  using prefix##Trigger = RemoteReceiverTrigger<prefix##Protocol>; \
278  using prefix##Dumper = RemoteReceiverDumper<prefix##Protocol>;
279 #define DECLARE_REMOTE_PROTOCOL(prefix) DECLARE_REMOTE_PROTOCOL_(prefix)
280 
281 } // namespace remote_base
282 } // namespace esphome
void register_listener(RemoteReceiverListener *listener)
Definition: remote_base.h:163
void set_data(const RawTimings &data)
Definition: remote_base.h:32
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
Definition: remote_base.h:146
int32_t operator[](uint32_t index) const
Definition: remote_base.h:50
const RawTimings & get_raw_data() const
Definition: remote_base.h:48
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:29
uint16_t x
Definition: tt21100.cpp:17
bool is_valid(uint32_t offset) const
Definition: remote_base.h:52
void item(uint32_t mark, uint32_t space)
Definition: remote_base.h:24
RemoteReceiveData(const RawTimings &data, uint8_t tolerance)
Definition: remote_base.h:45
std::vector< RemoteReceiverDumperBase * > dumpers_
Definition: remote_base.h:176
void set_data(typename T::ProtocolData data)
Definition: remote_base.h:214
std::vector< RemoteReceiverDumperBase * > secondary_dumpers_
Definition: remote_base.h:177
void set_transmitter(RemoteTransmitterBase *transmitter)
Definition: remote_base.h:238
RemoteComponentBase(InternalGPIOPin *pin)
Definition: remote_base.h:79
RemoteComponentBase * remote_base_
Definition: remote_base.h:103
std::vector< int32_t > RawTimings
Definition: remote_base.h:18
RemoteTransmitterBase * transmitter_
Definition: remote_base.h:245
int32_t lower_bound_(uint32_t length) const
Definition: remote_base.h:69
int32_t peek(uint32_t offset=0) const
Definition: remote_base.h:53
std::vector< RemoteReceiverListener * > listeners_
Definition: remote_base.h:175
void transmit(const typename Protocol::ProtocolData &data, uint32_t send_times=1, uint32_t send_wait=0)
Definition: remote_base.h:132
RemoteReceiverBase(InternalGPIOPin *pin)
Definition: remote_base.h:162
bool on_receive(RemoteReceiveData src) override
Definition: remote_base.h:223
bool dump(RemoteReceiveData src) override
Definition: remote_base.h:265
void set_clock_divider(uint8_t clock_divider)
Definition: remote_base.h:92
std::string size_t len
Definition: helpers.h:292
void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times=1, uint32_t send_wait=0)
Definition: remote_base.h:242
bool peek_item(uint32_t mark, uint32_t space, uint32_t offset=0) const
Definition: remote_base.h:57
uint16_t length
Definition: tt21100.cpp:12
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
bool matches(RemoteReceiveData src) override
Definition: remote_base.h:207
void advance(uint32_t amount=1)
Definition: remote_base.h:65
const RawTimings & get_data() const
Definition: remote_base.h:31
void set_tolerance(uint8_t tolerance)
Definition: remote_base.h:165
uint32_t to_microseconds_(uint32_t ticks)
Definition: remote_base.h:99
RemoteTransmittable(RemoteTransmitterBase *transmitter)
Definition: remote_base.h:237
int32_t upper_bound_(uint32_t length) const
Definition: remote_base.h:70
uint32_t from_microseconds_(uint32_t us)
Definition: remote_base.h:95