1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-18 03:02:20 +01:00

Coolix IR protocol improvements (#5105)

* coolix protocol

* tests

* 24-bit range

* some DRY in coolix

* added short condition

* one more change

* final prettify

* v2023.8
This commit is contained in:
Sergey Dudanov
2023-07-23 00:15:37 +04:00
committed by GitHub
parent 80154b280e
commit 827b2def1e
5 changed files with 130 additions and 45 deletions

View File

@@ -15,11 +15,21 @@ static const int32_t BIT_ZERO_SPACE_US = 1 * TICK_US;
static const int32_t FOOTER_MARK_US = 1 * TICK_US;
static const int32_t FOOTER_SPACE_US = 10 * TICK_US;
static void encode_data(RemoteTransmitData *dst, const CoolixData &src) {
// Break data into bytes, starting at the Most Significant
// Byte. Each byte then being sent normal, then followed inverted.
bool CoolixData::operator==(const CoolixData &other) const {
if (this->first == 0)
return this->second == other.first || this->second == other.second;
if (other.first == 0)
return other.second == this->first || other.second == this->second;
return this->first == other.first && this->second == other.second;
}
static void encode_frame(RemoteTransmitData *dst, const uint32_t &src) {
// Append header
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
// Break data into bytes, starting at the Most Significant
// Byte. Each byte then being sent normal, then followed inverted.
for (unsigned shift = 16;; shift -= 8) {
// Grab a bytes worth of data.
// Grab a bytes worth of data
const uint8_t byte = src >> shift;
// Normal
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
@@ -27,27 +37,33 @@ static void encode_data(RemoteTransmitData *dst, const CoolixData &src) {
// Inverted
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
dst->item(BIT_MARK_US, (byte & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US);
// Data end
if (shift == 0)
// End of frame
if (shift == 0) {
// Append footer
dst->mark(FOOTER_MARK_US);
break;
}
}
}
void CoolixProtocol::encode(RemoteTransmitData *dst, const CoolixData &data) {
dst->set_carrier_frequency(38000);
dst->reserve(2 + 2 * 48 + 2 + 2 + 2 * 48 + 1);
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
encode_data(dst, data);
dst->item(FOOTER_MARK_US, FOOTER_SPACE_US);
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
encode_data(dst, data);
dst->mark(FOOTER_MARK_US);
dst->reserve(100 + 100 * data.has_second());
encode_frame(dst, data.first);
if (data.has_second()) {
dst->space(FOOTER_SPACE_US);
encode_frame(dst, data.second);
}
}
static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
static bool decode_frame(RemoteReceiveData &src, uint32_t &dst) {
// Checking for header
if (!src.expect_item(HEADER_MARK_US, HEADER_SPACE_US))
return false;
// Reading data
uint32_t data = 0;
for (unsigned n = 3;; data <<= 8) {
// Read byte
// Reading byte
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
if (!src.expect_mark(BIT_MARK_US))
return false;
@@ -57,13 +73,16 @@ static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
return false;
}
}
// Check for inverse byte
// Checking for inverted byte
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
if (!src.expect_item(BIT_MARK_US, (data & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US))
return false;
}
// Checking the end of reading
// End of frame
if (--n == 0) {
// Checking for footer
if (!src.expect_mark(FOOTER_MARK_US))
return false;
dst = data;
return true;
}
@@ -71,15 +90,24 @@ static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
}
optional<CoolixData> CoolixProtocol::decode(RemoteReceiveData data) {
CoolixData first, second;
if (data.expect_item(HEADER_MARK_US, HEADER_SPACE_US) && decode_data(data, first) &&
data.expect_item(FOOTER_MARK_US, FOOTER_SPACE_US) && data.expect_item(HEADER_MARK_US, HEADER_SPACE_US) &&
decode_data(data, second) && data.expect_mark(FOOTER_MARK_US) && first == second)
return first;
return {};
CoolixData result;
const auto size = data.size();
if ((size != 200 && size != 100) || !decode_frame(data, result.first))
return {};
if (size == 100 || !data.expect_space(FOOTER_SPACE_US) || !decode_frame(data, result.second))
result.second = 0;
return result;
}
void CoolixProtocol::dump(const CoolixData &data) { ESP_LOGD(TAG, "Received Coolix: 0x%06X", data); }
void CoolixProtocol::dump(const CoolixData &data) {
if (data.is_strict()) {
ESP_LOGD(TAG, "Received Coolix: 0x%06X", data.first);
} else if (data.has_second()) {
ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second);
} else {
ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X]", data.first);
}
}
} // namespace remote_base
} // namespace esphome