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_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,79 +135,96 @@ 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, | ||||||
|   } |               "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.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)); | ||||||
|  |  | ||||||
|   ESP_LOGVV(TAG, |     // If first preamble item is a space, skip it | ||||||
|             "Decode Drayton: %" PRId32 ", %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 |     if (src.peek_space_at_least(1)) { | ||||||
|             " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 |       src.advance(1); | ||||||
|             " %" 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)); |  | ||||||
|  |  | ||||||
|   // If first preamble item is a space, skip it |     // Look for sync pulse, after. If sucessful index points to space of sync symbol | ||||||
|   if (src.peek_space_at_least(1)) { |     while (src.size() - src.get_index() >= NDATABITS) { | ||||||
|     src.advance(1); |       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); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|   // Look for sync pulse, after. If sucessful index points to space of sync symbol |     // No point continuing if not enough samples remaining to complete a packet | ||||||
|   for (uint16_t preamble = 0; preamble <= NBITS_PREAMBLE * 2; preamble += 2) { |     if (src.size() - src.get_index() < NDATABITS) { | ||||||
|     ESP_LOGVV(TAG, "Decode Drayton: preamble %d  %" PRId32 " %" PRId32, preamble, src.peek(preamble), |       ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index()); | ||||||
|               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); |  | ||||||
|       break; |       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; | ||||||
|   if (src.expect_space(3 * BIT_TIME_US) && (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * BIT_TIME_US))) { |     ESP_LOGVV(TAG, "Decode Drayton: first bit %d  %" PRId32 ", %" PRId32, src.peek(0), src.peek(1), src.peek(2)); | ||||||
|     out_data |= 0 << bit; |     if (src.expect_space(3 * BIT_TIME_US) && (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * 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))) { |  | ||||||
|     out_data |= 1 << bit; |  | ||||||
|   } else { |  | ||||||
|     ESP_LOGV(TAG, "Decode Drayton: Fail 1, - %" PRIu32, src.get_index()); |  | ||||||
|     return {}; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // Before/after each bit is read the index points to the transition at the start of the bit period or, |  | ||||||
|   // if there is no transition at the start of the bit period, then the transition in the middle of |  | ||||||
|   // the previous bit period. |  | ||||||
|   while (--bit >= 1) { |  | ||||||
|     ESP_LOGVV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data); |  | ||||||
|     if ((src.expect_space(BIT_TIME_US) || src.expect_space(2 * 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_mark(BIT_TIME_US) || src.expect_mark(2 * 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_LOGVV(TAG, "Decode Drayton: Fail 2, %2d %08" PRIx32, bit, out_data); |       ESP_LOGV(TAG, "Decode Drayton: Fail 2, - %d %d %d", src.peek(-1), src.peek(0), src.peek(1)); | ||||||
|       return {}; |       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; |  | ||||||
|   } |  | ||||||
|   ESP_LOGV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data); |  | ||||||
|  |  | ||||||
|   out.channel = (uint8_t) (out_data & 0x1F); |     // Before/after each bit is read the index points to the transition at the start of the bit period or, | ||||||
|   out_data >>= NBITS_CHANNEL; |     // if there is no transition at the start of the bit period, then the transition in the middle of | ||||||
|   out.command = (uint8_t) (out_data & 0x7F); |     // the previous bit period. | ||||||
|   out_data >>= NBITS_COMMAND; |     while (--bit >= 1) { | ||||||
|   out.address = (uint16_t) (out_data & 0xFFFF); |       ESP_LOGVV(TAG, "Decode Drayton: Data, %2d %08" PRIx32, bit, out_data); | ||||||
|  |       if ((src.expect_space(BIT_TIME_US) || src.expect_space(2 * BIT_TIME_US)) && | ||||||
|  |           (src.expect_mark(BIT_TIME_US) || src.peek_mark(2 * BIT_TIME_US))) { | ||||||
|  |         out_data |= 0 << bit; | ||||||
|  |       } else if ((src.expect_mark(BIT_TIME_US) || src.expect_mark(2 * BIT_TIME_US)) && | ||||||
|  |                  (src.expect_space(BIT_TIME_US) || src.peek_space(2 * BIT_TIME_US))) { | ||||||
|  |         out_data |= 1 << bit; | ||||||
|  |       } else { | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|   return out; |     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 %08x", bit, out_data); | ||||||
|  |  | ||||||
|  |     out.channel = (uint8_t) (out_data & 0x1F); | ||||||
|  |     out_data >>= NBITS_CHANNEL; | ||||||
|  |     out.command = (uint8_t) (out_data & 0x7F); | ||||||
|  |     out_data >>= NBITS_COMMAND; | ||||||
|  |     out.address = (uint16_t) (out_data & 0xFFFF); | ||||||
|  |  | ||||||
|  |     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, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user