mirror of
https://github.com/esphome/esphome.git
synced 2025-04-02 08:58:17 +01:00
124 lines
4.5 KiB
C++
124 lines
4.5 KiB
C++
#include "abbwelcome_protocol.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome {
|
|
namespace remote_base {
|
|
|
|
static const char *const TAG = "remote.abbwelcome";
|
|
|
|
static const uint32_t BIT_ONE_SPACE_US = 102;
|
|
static const uint32_t BIT_ZERO_MARK_US = 32; // 18-44
|
|
static const uint32_t BIT_ZERO_SPACE_US = BIT_ONE_SPACE_US - BIT_ZERO_MARK_US;
|
|
static const uint16_t BYTE_SPACE_US = 210;
|
|
|
|
uint8_t ABBWelcomeData::calc_cs_() const {
|
|
uint8_t checksum = 0;
|
|
for (uint8_t i = 0; i < this->size() - 1; i++) {
|
|
uint16_t temp = checksum ^ (this->data_[i]);
|
|
temp = temp ^ (uint16_t) (((uint32_t) temp << 0x11) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x12) >> 0x10) ^
|
|
(uint16_t) (((uint32_t) temp << 0x13) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x14) >> 0x10) ^
|
|
(uint16_t) (((uint32_t) temp << 0x15) >> 0x10) ^ (uint16_t) (((uint32_t) temp << 0x16) >> 0x10) ^
|
|
(uint16_t) (((uint32_t) temp << 0x17) >> 0x10);
|
|
checksum = (temp & 0xfe) ^ ((temp >> 8) & 1);
|
|
}
|
|
return ~checksum;
|
|
}
|
|
|
|
void ABBWelcomeProtocol::encode_byte_(RemoteTransmitData *dst, uint8_t data) const {
|
|
// space = bus high, mark = activate bus pulldown
|
|
dst->mark(BIT_ZERO_MARK_US);
|
|
uint32_t next_space = BIT_ZERO_SPACE_US;
|
|
for (uint8_t mask = 1 << 7; mask; mask >>= 1) {
|
|
if (data & mask) {
|
|
next_space += BIT_ONE_SPACE_US;
|
|
} else {
|
|
dst->space(next_space);
|
|
dst->mark(BIT_ZERO_MARK_US);
|
|
next_space = BIT_ZERO_SPACE_US;
|
|
}
|
|
}
|
|
next_space += BYTE_SPACE_US;
|
|
dst->space(next_space);
|
|
}
|
|
|
|
void ABBWelcomeProtocol::encode(RemoteTransmitData *dst, const ABBWelcomeData &src) {
|
|
dst->set_carrier_frequency(0);
|
|
uint32_t reserve_count = 0;
|
|
for (size_t i = 0; i < src.size(); i++) {
|
|
reserve_count += 2 * (9 - (src[i] & 1) - ((src[i] >> 1) & 1) - ((src[i] >> 2) & 1) - ((src[i] >> 3) & 1) -
|
|
((src[i] >> 4) & 1) - ((src[i] >> 5) & 1) - ((src[i] >> 6) & 1) - ((src[i] >> 7) & 1));
|
|
}
|
|
dst->reserve(reserve_count);
|
|
for (size_t i = 0; i < src.size(); i++)
|
|
this->encode_byte_(dst, src[i]);
|
|
ESP_LOGD(TAG, "Transmitting: %s", src.to_string().c_str());
|
|
}
|
|
|
|
bool ABBWelcomeProtocol::decode_byte_(RemoteReceiveData &src, bool &done, uint8_t &data) {
|
|
if (!src.expect_mark(BIT_ZERO_MARK_US))
|
|
return false;
|
|
uint32_t next_space = BIT_ZERO_SPACE_US;
|
|
for (uint8_t mask = 1 << 7; mask; mask >>= 1) {
|
|
// if (!src.peek_space_at_least(next_space, 0))
|
|
// return false;
|
|
if (src.expect_space(next_space)) {
|
|
if (!src.expect_mark(BIT_ZERO_MARK_US))
|
|
return false;
|
|
next_space = BIT_ZERO_SPACE_US;
|
|
} else {
|
|
data |= mask;
|
|
next_space += BIT_ONE_SPACE_US;
|
|
}
|
|
}
|
|
next_space += BYTE_SPACE_US;
|
|
// if (!src.peek_space_at_least(next_space, 0))
|
|
// return false;
|
|
done = !(src.expect_space(next_space));
|
|
return true;
|
|
}
|
|
|
|
optional<ABBWelcomeData> ABBWelcomeProtocol::decode(RemoteReceiveData src) {
|
|
if (src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US) &&
|
|
src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
|
|
src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
|
|
src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US) &&
|
|
src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + BIT_ONE_SPACE_US + BYTE_SPACE_US) &&
|
|
src.expect_item(BIT_ZERO_MARK_US, BIT_ZERO_SPACE_US + 8 * BIT_ONE_SPACE_US + BYTE_SPACE_US)) {
|
|
ESP_LOGVV(TAG, "Received Header: 0x55FF");
|
|
ABBWelcomeData out;
|
|
out[0] = 0x55;
|
|
out[1] = 0xff;
|
|
bool done = false;
|
|
uint8_t length = 10;
|
|
uint8_t received_bytes = 2;
|
|
for (; (received_bytes < length) && !done; received_bytes++) {
|
|
uint8_t data = 0;
|
|
if (!this->decode_byte_(src, done, data)) {
|
|
ESP_LOGW(TAG, "Received incomplete packet: %s", out.to_string(received_bytes).c_str());
|
|
return {};
|
|
}
|
|
if (received_bytes == 2) {
|
|
length += std::min(static_cast<uint8_t>(data & DATA_LENGTH_MASK), MAX_DATA_LENGTH);
|
|
if (data & 0x40) {
|
|
length += 2;
|
|
}
|
|
}
|
|
ESP_LOGVV(TAG, "Received Byte: 0x%02X", data);
|
|
out[received_bytes] = data;
|
|
}
|
|
if (out.is_valid()) {
|
|
ESP_LOGI(TAG, "Received: %s", out.to_string().c_str());
|
|
return out;
|
|
}
|
|
ESP_LOGW(TAG, "Received malformed packet: %s", out.to_string(received_bytes).c_str());
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void ABBWelcomeProtocol::dump(const ABBWelcomeData &data) {
|
|
ESP_LOGD(TAG, "Received ABBWelcome: %s", data.to_string().c_str());
|
|
}
|
|
|
|
} // namespace remote_base
|
|
} // namespace esphome
|