ESPHome  2024.4.2
abbwelcome_protocol.cpp
Go to the documentation of this file.
1 #include "abbwelcome_protocol.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace remote_base {
6 
7 static const char *const TAG = "remote.abbwelcome";
8 
9 static const uint32_t BIT_ONE_SPACE_US = 102;
10 static const uint32_t BIT_ZERO_MARK_US = 32; // 18-44
11 static const uint32_t BIT_ZERO_SPACE_US = BIT_ONE_SPACE_US - BIT_ZERO_MARK_US;
12 static const uint16_t BYTE_SPACE_US = 210;
13 
14 uint8_t ABBWelcomeData::calc_cs_() const {
15  uint8_t checksum = 0;
16  for (uint8_t i = 0; i < this->size() - 1; i++) {
17  uint16_t temp = checksum ^ (this->data_[i]);
18  temp = temp ^ (uint16_t) (((uint32_t) temp << 0x11) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x12) >> 0x10) ^
19  (uint16_t) (((uint32_t) temp << 0x13) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x14) >> 0x10) ^
20  (uint16_t) (((uint32_t) temp << 0x15) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x16) >> 0x10) ^
21  (uint16_t) (((uint32_t) temp << 0x17) >> 0x10);
22  checksum = (temp & 0xfe) ^ ((temp >> 8) & 1);
23  }
24  return ~checksum;
25 }
26 
28  // space = bus high, mark = activate bus pulldown
29  dst->mark(BIT_ZERO_MARK_US);
30  uint32_t next_space = BIT_ZERO_SPACE_US;
31  for (uint8_t mask = 1 << 7; mask; mask >>= 1) {
32  if (data & mask) {
33  next_space += BIT_ONE_SPACE_US;
34  } else {
35  dst->space(next_space);
36  dst->mark(BIT_ZERO_MARK_US);
37  next_space = BIT_ZERO_SPACE_US;
38  }
39  }
40  next_space += BYTE_SPACE_US;
41  dst->space(next_space);
42 }
43 
45  dst->set_carrier_frequency(0);
46  uint32_t reserve_count = 0;
47  for (size_t i = 0; i < src.size(); i++) {
48  reserve_count += 2 * (9 - (src[i] & 1) - ((src[i] >> 1) & 1) - ((src[i] >> 2) & 1) - ((src[i] >> 3) & 1) -
49  ((src[i] >> 4) & 1) - ((src[i] >> 5) & 1) - ((src[i] >> 6) & 1) - ((src[i] >> 7) & 1));
50  }
51  dst->reserve(reserve_count);
52  for (size_t i = 0; i < src.size(); i++)
53  this->encode_byte_(dst, src[i]);
54  ESP_LOGD(TAG, "Transmitting: %s", src.to_string().c_str());
55 }
56 
57 bool ABBWelcomeProtocol::decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data) {
58  if (!src.expect_mark(BIT_ZERO_MARK_US))
59  return false;
60  uint32_t next_space = BIT_ZERO_SPACE_US;
61  for (uint8_t mask = 1 << 7; mask; mask >>= 1) {
62  // if (!src.peek_space_at_least(next_space, 0))
63  // return false;
64  if (src.expect_space(next_space)) {
65  if (!src.expect_mark(BIT_ZERO_MARK_US))
66  return false;
67  next_space = BIT_ZERO_SPACE_US;
68  } else {
69  data |= mask;
70  next_space += BIT_ONE_SPACE_US;
71  }
72  }
73  next_space += BYTE_SPACE_US;
74  // if (!src.peek_space_at_least(next_space, 0))
75  // return false;
76  done = !(src.expect_space(next_space));
77  return true;
78 }
79 
81  if (src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US) &&
82  src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
83  src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
84  src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
85  src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US + BYTE_SPACE_US) &&
86  src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + 8 * BIT_ONE_SPACE_US + BYTE_SPACE_US)) {
87  ESP_LOGVV(TAG, "Received Header: 0x55FF");
88  ABBWelcomeData out;
89  out[0] = 0x55;
90  out[1] = 0xff;
91  bool done = false;
92  uint8_t length = 10;
93  uint8_t received_bytes = 2;
94  for (; (received_bytes < length) && !done; received_bytes++) {
95  uint8_t data = 0;
96  if (!this->decode_byte_(src, done, data)) {
97  ESP_LOGW(TAG, "Received incomplete packet: %s", out.to_string(received_bytes).c_str());
98  return {};
99  }
100  if (received_bytes == 2) {
101  length += std::min(static_cast<uint8_t>(data & DATA_LENGTH_MASK), MAX_DATA_LENGTH);
102  if (data & 0x40) {
103  length += 2;
104  }
105  }
106  ESP_LOGVV(TAG, "Received Byte: 0x%02X", data);
107  out[received_bytes] = data;
108  }
109  if (out.is_valid()) {
110  ESP_LOGI(TAG, "Received: %s", out.to_string().c_str());
111  return out;
112  }
113  ESP_LOGW(TAG, "Received malformed packet: %s", out.to_string(received_bytes).c_str());
114  }
115  return {};
116 }
117 
119  ESP_LOGD(TAG, "Received ABBWelcome: %s", data.to_string().c_str());
120 }
121 
122 } // namespace remote_base
123 } // namespace esphome
void encode_byte_(RemoteTransmitData *dst, uint8_t data) const
optional< ABBWelcomeData > decode(RemoteReceiveData src) override
void set_carrier_frequency(uint32_t carrier_frequency)
Definition: remote_base.h:29
bool decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data)
std::array< uint8_t, 12+MAX_DATA_LENGTH > data_
std::string to_string(uint8_t max_print_bytes=255) const
uint8_t checksum
Definition: bl0939.h:35
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
void encode(RemoteTransmitData *dst, const ABBWelcomeData &src) override
bool expect_item(uint32_t mark, uint32_t space)
Definition: remote_base.cpp:74
void dump(const ABBWelcomeData &data) override