mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 21:44:55 +01:00
Improvements to RF receiver for Drayton Digistat heating controller (#5504)
This commit is contained in:
parent
d73ad39aed
commit
222bb9b495
1 changed files with 80 additions and 62 deletions
|
@ -13,7 +13,8 @@ static const uint8_t NBITS_SYNC = 4;
|
||||||
static const uint8_t NBITS_ADDRESS = 16;
|
static const uint8_t NBITS_ADDRESS = 16;
|
||||||
static const uint8_t NBITS_CHANNEL = 5;
|
static const uint8_t NBITS_CHANNEL = 5;
|
||||||
static const uint8_t NBITS_COMMAND = 7;
|
static const uint8_t NBITS_COMMAND = 7;
|
||||||
static const uint8_t NBITS = NBITS_ADDRESS + NBITS_CHANNEL + NBITS_COMMAND;
|
static const uint8_t NDATABITS = NBITS_ADDRESS + NBITS_CHANNEL + NBITS_COMMAND;
|
||||||
|
static const uint8_t MIN_RX_SRC = (NDATABITS * 2 + NBITS_SYNC / 2);
|
||||||
|
|
||||||
static const uint8_t CMD_ON = 0x41;
|
static const uint8_t CMD_ON = 0x41;
|
||||||
static const uint8_t CMD_OFF = 0x02;
|
static const uint8_t CMD_OFF = 0x02;
|
||||||
|
@ -116,7 +117,7 @@ void DraytonProtocol::encode(RemoteTransmitData *dst, const DraytonData &data) {
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Send Drayton: out_data %08" PRIx32, out_data);
|
ESP_LOGV(TAG, "Send Drayton: out_data %08" PRIx32, out_data);
|
||||||
|
|
||||||
for (uint32_t mask = 1UL << (NBITS - 1); mask != 0; mask >>= 1) {
|
for (uint32_t mask = 1UL << (NDATABITS - 1); mask != 0; mask >>= 1) {
|
||||||
if (out_data & mask) {
|
if (out_data & mask) {
|
||||||
dst->mark(BIT_TIME_US);
|
dst->mark(BIT_TIME_US);
|
||||||
dst->space(BIT_TIME_US);
|
dst->space(BIT_TIME_US);
|
||||||
|
@ -134,17 +135,14 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||||
.command = 0,
|
.command = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (src.size() < 45) {
|
while (src.size() - src.get_index() > MIN_RX_SRC) {
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGVV(TAG,
|
ESP_LOGVV(TAG,
|
||||||
"Decode Drayton: %" PRId32 ", %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
"Decode Drayton: %" PRId32 ", %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
||||||
" %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
" %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
||||||
" %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 "",
|
" %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 "",
|
||||||
src.size(), src.peek(0), src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6),
|
src.size() - src.get_index(), src.peek(0), src.peek(1), src.peek(2), src.peek(3), src.peek(4),
|
||||||
src.peek(7), src.peek(8), src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14),
|
src.peek(5), src.peek(6), src.peek(7), src.peek(8), src.peek(9), src.peek(10), src.peek(11), src.peek(12),
|
||||||
src.peek(15), src.peek(16), src.peek(17), src.peek(18), src.peek(19));
|
src.peek(13), src.peek(14), src.peek(15), src.peek(16), src.peek(17), src.peek(18), src.peek(19));
|
||||||
|
|
||||||
// If first preamble item is a space, skip it
|
// If first preamble item is a space, skip it
|
||||||
if (src.peek_space_at_least(1)) {
|
if (src.peek_space_at_least(1)) {
|
||||||
|
@ -152,29 +150,39 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for sync pulse, after. If sucessful index points to space of sync symbol
|
// Look for sync pulse, after. If sucessful index points to space of sync symbol
|
||||||
for (uint16_t preamble = 0; preamble <= NBITS_PREAMBLE * 2; preamble += 2) {
|
while (src.size() - src.get_index() >= NDATABITS) {
|
||||||
ESP_LOGVV(TAG, "Decode Drayton: preamble %d %" PRId32 " %" PRId32, preamble, src.peek(preamble),
|
ESP_LOGVV(TAG, "Decode Drayton: sync search %d, %" PRId32 " %" PRId32, src.size() - src.get_index(), src.peek(),
|
||||||
src.peek(preamble + 1));
|
src.peek(1));
|
||||||
if (src.peek_mark(2 * BIT_TIME_US, preamble) &&
|
if (src.peek_mark(2 * BIT_TIME_US) &&
|
||||||
(src.peek_space(2 * BIT_TIME_US, preamble + 1) || src.peek_space(3 * BIT_TIME_US, preamble + 1))) {
|
(src.peek_space(2 * BIT_TIME_US, 1) || src.peek_space(3 * BIT_TIME_US, 1))) {
|
||||||
src.advance(preamble + 1);
|
src.advance(1);
|
||||||
|
ESP_LOGVV(TAG, "Decode Drayton: Found SYNC, - %d", src.get_index());
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
src.advance(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No point continuing if not enough samples remaining to complete a packet
|
||||||
|
if (src.size() - src.get_index() < NDATABITS) {
|
||||||
|
ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Read data. Index points to space of sync symbol
|
// Read data. Index points to space of sync symbol
|
||||||
// Extract first bit
|
// Extract first bit
|
||||||
// Checks next bit to leave index pointing correctly
|
// Checks next bit to leave index pointing correctly
|
||||||
uint32_t out_data = 0;
|
uint32_t out_data = 0;
|
||||||
uint8_t bit = NBITS_ADDRESS + NBITS_COMMAND + NBITS_CHANNEL - 1;
|
uint8_t bit = NDATABITS - 1;
|
||||||
|
ESP_LOGVV(TAG, "Decode Drayton: first bit %d %" PRId32 ", %" PRId32, src.peek(0), src.peek(1), src.peek(2));
|
||||||
if (src.expect_space(3 * BIT_TIME_US) && (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * BIT_TIME_US))) {
|
if (src.expect_space(3 * BIT_TIME_US) && (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * BIT_TIME_US))) {
|
||||||
out_data |= 0 << bit;
|
out_data |= 0 << bit;
|
||||||
} else if (src.expect_space(2 * BIT_TIME_US) && src.expect_mark(BIT_TIME_US) &&
|
} else if (src.expect_space(2 * BIT_TIME_US) && src.expect_mark(BIT_TIME_US) &&
|
||||||
(src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) {
|
(src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) {
|
||||||
out_data |= 1 << bit;
|
out_data |= 1 << bit;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index());
|
ESP_LOGV(TAG, "Decode Drayton: Fail 2, - %d %d %d", src.peek(-1), src.peek(0), src.peek(1));
|
||||||
return {};
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before/after each bit is read the index points to the transition at the start of the bit period or,
|
// Before/after each bit is read the index points to the transition at the start of the bit period or,
|
||||||
|
@ -189,16 +197,24 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||||
(src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) {
|
(src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) {
|
||||||
out_data |= 1 << bit;
|
out_data |= 1 << bit;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGVV(TAG, "Decode Drayton: Fail 2, %2d %08" PRIx32, bit, out_data);
|
break;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bit > 0) {
|
||||||
|
ESP_LOGVV(TAG, "Decode Drayton: Fail 3, %d %" PRId32 " %" PRId32, src.peek(-1), src.peek(0), src.peek(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (src.expect_space(BIT_TIME_US) || src.expect_space(2 * BIT_TIME_US)) {
|
if (src.expect_space(BIT_TIME_US) || src.expect_space(2 * BIT_TIME_US)) {
|
||||||
out_data |= 0;
|
out_data |= 0;
|
||||||
} else if (src.expect_mark(BIT_TIME_US) || src.expect_mark(2 * BIT_TIME_US)) {
|
} else if (src.expect_mark(BIT_TIME_US) || src.expect_mark(2 * BIT_TIME_US)) {
|
||||||
out_data |= 1;
|
out_data |= 1;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data);
|
|
||||||
|
ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08x", bit, out_data);
|
||||||
|
|
||||||
out.channel = (uint8_t) (out_data & 0x1F);
|
out.channel = (uint8_t) (out_data & 0x1F);
|
||||||
out_data >>= NBITS_CHANNEL;
|
out_data >>= NBITS_CHANNEL;
|
||||||
|
@ -207,6 +223,8 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||||
out.address = (uint16_t) (out_data & 0xFFFF);
|
out.address = (uint16_t) (out_data & 0xFFFF);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
void DraytonProtocol::dump(const DraytonData &data) {
|
void DraytonProtocol::dump(const DraytonData &data) {
|
||||||
ESP_LOGI(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address,
|
ESP_LOGI(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address,
|
||||||
|
|
Loading…
Reference in a new issue