ESPHome  2024.11.0
midea_protocol.cpp
Go to the documentation of this file.
1 #include "midea_protocol.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace remote_base {
6 
7 static const char *const TAG = "remote.midea";
8 
9 static const int32_t TICK_US = 560;
10 static const int32_t HEADER_MARK_US = 8 * TICK_US;
11 static const int32_t HEADER_SPACE_US = 8 * TICK_US;
12 static const int32_t BIT_MARK_US = 1 * TICK_US;
13 static const int32_t BIT_ONE_SPACE_US = 3 * TICK_US;
14 static const int32_t BIT_ZERO_SPACE_US = 1 * TICK_US;
15 static const int32_t FOOTER_MARK_US = 1 * TICK_US;
16 static const int32_t FOOTER_SPACE_US = 10 * TICK_US;
17 
18 uint8_t MideaData::calc_cs_() const {
19  uint8_t cs = 0;
20  for (uint8_t idx = 0; idx < OFFSET_CS; idx++)
21  cs -= reverse_bits(this->data_[idx]);
22  return reverse_bits(cs);
23 }
24 
25 bool MideaData::is_compliment(const MideaData &rhs) const {
26  return std::equal(this->data_.begin(), this->data_.end(), rhs.data_.begin(),
27  [](const uint8_t &a, const uint8_t &b) { return a + b == 255; });
28 }
29 
31  dst->set_carrier_frequency(38000);
32  dst->reserve(2 + 48 * 2 + 2 + 2 + 48 * 2 + 1);
33  dst->item(HEADER_MARK_US, HEADER_SPACE_US);
34  for (unsigned idx = 0; idx < 6; idx++) {
35  for (uint8_t mask = 1 << 7; mask; mask >>= 1)
36  dst->item(BIT_MARK_US, (src[idx] & mask) ? BIT_ONE_SPACE_US : BIT_ZERO_SPACE_US);
37  }
38  dst->item(FOOTER_MARK_US, FOOTER_SPACE_US);
39  dst->item(HEADER_MARK_US, HEADER_SPACE_US);
40  for (unsigned idx = 0; idx < 6; idx++) {
41  for (uint8_t mask = 1 << 7; mask; mask >>= 1)
42  dst->item(BIT_MARK_US, (src[idx] & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US);
43  }
44  dst->mark(FOOTER_MARK_US);
45 }
46 
47 static bool decode_data(RemoteReceiveData &src, MideaData &dst) {
48  for (unsigned idx = 0; idx < 6; idx++) {
49  uint8_t data = 0;
50  for (uint8_t mask = 1 << 7; mask; mask >>= 1) {
51  if (!src.expect_mark(BIT_MARK_US))
52  return false;
53  if (src.expect_space(BIT_ONE_SPACE_US)) {
54  data |= mask;
55  } else if (!src.expect_space(BIT_ZERO_SPACE_US)) {
56  return false;
57  }
58  }
59  dst[idx] = data;
60  }
61  return true;
62 }
63 
65  MideaData out, inv;
66  if (src.expect_item(HEADER_MARK_US, HEADER_SPACE_US) && decode_data(src, out) && out.is_valid() &&
67  src.expect_item(FOOTER_MARK_US, FOOTER_SPACE_US) && src.expect_item(HEADER_MARK_US, HEADER_SPACE_US) &&
68  decode_data(src, inv) && src.expect_mark(FOOTER_MARK_US) && out.is_compliment(inv))
69  return out;
70  return {};
71 }
72 
73 void MideaProtocol::dump(const MideaData &data) { ESP_LOGI(TAG, "Received Midea: %s", data.to_string().c_str()); }
74 
75 } // namespace remote_base
76 } // namespace esphome
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:34
void item(uint32_t mark, uint32_t space)
Definition: remote_base.h:29
bool is_compliment(const MideaData &rhs) const
void encode(RemoteTransmitData *dst, const MideaData &src) override
uint8_t reverse_bits(uint8_t x)
Reverse the order of 8 bits.
Definition: helpers.h:223
static const uint8_t OFFSET_CS
std::array< uint8_t, 6 > data_
std::string to_string() const
optional< MideaData > decode(RemoteReceiveData src) override
void dump(const MideaData &data) override
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:74