ESPHome  2024.11.0
coolix_protocol.cpp
Go to the documentation of this file.
1 #include "coolix_protocol.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace remote_base {
6 
7 static const char *const TAG = "remote.coolix";
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 bool CoolixData::operator==(const CoolixData &other) const {
19  if (this->first == 0)
20  return this->second == other.first || this->second == other.second;
21  if (other.first == 0)
22  return other.second == this->first || other.second == this->second;
23  return this->first == other.first && this->second == other.second;
24 }
25 
26 static void encode_frame(RemoteTransmitData *dst, const uint32_t &src) {
27  // Append header
28  dst->item(HEADER_MARK_US, HEADER_SPACE_US);
29  // Break data into bytes, starting at the Most Significant
30  // Byte. Each byte then being sent normal, then followed inverted.
31  for (unsigned shift = 16;; shift -= 8) {
32  // Grab a bytes worth of data
33  const uint8_t byte = src >> shift;
34  // Normal
35  for (uint8_t mask = 1 << 7; mask; mask >>= 1)
36  dst->item(BIT_MARK_US, (byte & mask) ? BIT_ONE_SPACE_US : BIT_ZERO_SPACE_US);
37  // Inverted
38  for (uint8_t mask = 1 << 7; mask; mask >>= 1)
39  dst->item(BIT_MARK_US, (byte & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US);
40  // End of frame
41  if (shift == 0) {
42  // Append footer
43  dst->mark(FOOTER_MARK_US);
44  break;
45  }
46  }
47 }
48 
50  dst->set_carrier_frequency(38000);
51  dst->reserve(100 + 100 * data.has_second());
52  encode_frame(dst, data.first);
53  if (data.has_second()) {
54  dst->space(FOOTER_SPACE_US);
55  encode_frame(dst, data.second);
56  }
57 }
58 
59 static bool decode_frame(RemoteReceiveData &src, uint32_t &dst) {
60  // Checking for header
61  if (!src.expect_item(HEADER_MARK_US, HEADER_SPACE_US))
62  return false;
63  // Reading data
64  uint32_t data = 0;
65  for (unsigned n = 3;; data <<= 8) {
66  // Reading byte
67  for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
68  if (!src.expect_mark(BIT_MARK_US))
69  return false;
70  if (src.expect_space(BIT_ONE_SPACE_US)) {
71  data |= mask;
72  } else if (!src.expect_space(BIT_ZERO_SPACE_US)) {
73  return false;
74  }
75  }
76  // Checking for inverted byte
77  for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
78  if (!src.expect_item(BIT_MARK_US, (data & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US))
79  return false;
80  }
81  // End of frame
82  if (--n == 0) {
83  // Checking for footer
84  if (!src.expect_mark(FOOTER_MARK_US))
85  return false;
86  dst = data;
87  return true;
88  }
89  }
90 }
91 
93  CoolixData result;
94  const auto size = data.size();
95  if ((size != 200 && size != 100) || !decode_frame(data, result.first))
96  return {};
97  if (size == 100 || !data.expect_space(FOOTER_SPACE_US) || !decode_frame(data, result.second))
98  result.second = 0;
99  return result;
100 }
101 
102 void CoolixProtocol::dump(const CoolixData &data) {
103  if (data.is_strict()) {
104  ESP_LOGI(TAG, "Received Coolix: 0x%06" PRIX32, data.first);
105  } else if (data.has_second()) {
106  ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06" PRIX32 ", 0x%06" PRIX32 "]", data.first, data.second);
107  } else {
108  ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06" PRIX32 "]", data.first);
109  }
110 }
111 
112 } // namespace remote_base
113 } // namespace esphome
optional< CoolixData > decode(RemoteReceiveData data) override
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 operator==(const CoolixData &other) const
void encode(RemoteTransmitData *dst, const CoolixData &data) override
void dump(const CoolixData &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