mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Improvements to RF receiver for Drayton Digistat heating controller (#5504)
This commit is contained in:
		| @@ -13,7 +13,8 @@ static const uint8_t NBITS_SYNC = 4; | ||||
| static const uint8_t NBITS_ADDRESS = 16; | ||||
| static const uint8_t NBITS_CHANNEL = 5; | ||||
| 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_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); | ||||
|  | ||||
|   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) { | ||||
|       dst->mark(BIT_TIME_US); | ||||
|       dst->space(BIT_TIME_US); | ||||
| @@ -134,17 +135,14 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) { | ||||
|       .command = 0, | ||||
|   }; | ||||
|  | ||||
|   if (src.size() < 45) { | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   while (src.size() - src.get_index() > MIN_RX_SRC) { | ||||
|     ESP_LOGVV(TAG, | ||||
|               "Decode Drayton: %" 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.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(15), src.peek(16), src.peek(17), src.peek(18), src.peek(19)); | ||||
|               " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 | ||||
|               " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 "", | ||||
|               src.size() - src.get_index(), src.peek(0), src.peek(1), src.peek(2), src.peek(3), src.peek(4), | ||||
|               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(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 (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 | ||||
|   for (uint16_t preamble = 0; preamble <= NBITS_PREAMBLE * 2; preamble += 2) { | ||||
|     ESP_LOGVV(TAG, "Decode Drayton: preamble %d  %" PRId32 " %" PRId32, preamble, src.peek(preamble), | ||||
|               src.peek(preamble + 1)); | ||||
|     if (src.peek_mark(2 * BIT_TIME_US, preamble) && | ||||
|         (src.peek_space(2 * BIT_TIME_US, preamble + 1) || src.peek_space(3 * BIT_TIME_US, preamble + 1))) { | ||||
|       src.advance(preamble + 1); | ||||
|     while (src.size() - src.get_index() >= NDATABITS) { | ||||
|       ESP_LOGVV(TAG, "Decode Drayton: sync search %d, %" PRId32 " %" PRId32, src.size() - src.get_index(), src.peek(), | ||||
|                 src.peek(1)); | ||||
|       if (src.peek_mark(2 * BIT_TIME_US) && | ||||
|           (src.peek_space(2 * BIT_TIME_US, 1) || src.peek_space(3 * BIT_TIME_US, 1))) { | ||||
|         src.advance(1); | ||||
|         ESP_LOGVV(TAG, "Decode Drayton: Found SYNC, - %d", src.get_index()); | ||||
|         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 | ||||
|     // Extract first bit | ||||
|     // Checks next bit to leave index pointing correctly | ||||
|     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))) { | ||||
|       out_data |= 0 << bit; | ||||
|     } 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))) { | ||||
|       out_data |= 1 << bit; | ||||
|     } else { | ||||
|     ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index()); | ||||
|     return {}; | ||||
|       ESP_LOGV(TAG, "Decode Drayton: Fail 2, - %d %d %d", src.peek(-1), src.peek(0), src.peek(1)); | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     // 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))) { | ||||
|         out_data |= 1 << bit; | ||||
|       } else { | ||||
|       ESP_LOGVV(TAG, "Decode Drayton: Fail 2, %2d %08" PRIx32, bit, out_data); | ||||
|       return {}; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     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)) { | ||||
|       out_data |= 0; | ||||
|     } else if (src.expect_mark(BIT_TIME_US) || src.expect_mark(2 * BIT_TIME_US)) { | ||||
|       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_data >>= NBITS_CHANNEL; | ||||
| @@ -208,6 +224,8 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) { | ||||
|  | ||||
|     return out; | ||||
|   } | ||||
|   return {}; | ||||
| } | ||||
| void DraytonProtocol::dump(const DraytonData &data) { | ||||
|   ESP_LOGI(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address, | ||||
|            ((data.address << 1) & 0xffff), data.channel, data.command); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user