ESPHome  2024.4.2
byronsx_protocol.cpp
Go to the documentation of this file.
1 #include "byronsx_protocol.h"
2 #include "esphome/core/log.h"
3 
4 namespace esphome {
5 namespace remote_base {
6 
7 static const char *const TAG = "remote.byronsx";
8 
9 static const uint32_t BIT_TIME_US = 333;
10 static const uint8_t NBITS_ADDRESS = 8;
11 static const uint8_t NBITS_COMMAND = 4;
12 static const uint8_t NBITS_START_BIT = 1;
13 static const uint8_t NBITS_DATA = NBITS_ADDRESS + NBITS_COMMAND /*+ NBITS_COMMAND*/;
14 
15 /*
16 ByronSX Protocol
17 Each transmitted packet appears to consist of thirteen bits of PWM encoded
18 data. Each bit period of aprox 1ms consists of a transmitter OFF period
19 followed by a transmitter ON period. The 'on' and 'off' periods are either
20 short (approx 332us) or long (664us).
21 
22 A short 'off' followed by a long 'on' represents a '1' bit.
23 A long 'off' followed by a short 'on' represents a '0' bit.
24 
25 A the beginning of each packet is and initial 'off' period of approx 5.6ms
26 followed by a short 'on'.
27 
28 The data payload consists of twelve bits which appear to be an eight bit
29 address floowied by a 4 bit chime number.
30 
31 SAAAAAAAACCCC
32 
33 Whese:
34 S = the initial short start pulse
35 A = The eight address bits
36 C - The four chime bits
37 
38 --------------------
39 
40 I have also used 'RFLink' software (RLink Firmware Version: 1.1 Revision: 48)
41 to capture these packets, eg:
42 
43 20;19;Byron;ID=004f;SWITCH=02;CMD=ON;CHIME=02;
44 
45 This module transmits and interprets packets in the same way as RFLink.
46 
47 marshn
48 
49 */
50 
52  uint32_t out_data = 0x0;
53 
54  ESP_LOGD(TAG, "Send ByronSX: address=%04x command=%03x", data.address, data.command);
55 
56  out_data = data.address;
57  out_data <<= NBITS_COMMAND;
58  out_data |= data.command;
59 
60  ESP_LOGV(TAG, "Send ByronSX: out_data %03x", out_data);
61 
62  // Initial Mark start bit
63  dst->mark(1 * BIT_TIME_US);
64 
65  for (uint32_t mask = 1UL << (NBITS_DATA - 1); mask != 0; mask >>= 1) {
66  if (out_data & mask) {
67  dst->space(2 * BIT_TIME_US);
68  dst->mark(1 * BIT_TIME_US);
69  } else {
70  dst->space(1 * BIT_TIME_US);
71  dst->mark(2 * BIT_TIME_US);
72  }
73  }
74  // final space at end of packet
75  dst->space(17 * BIT_TIME_US);
76 }
77 
79  ByronSXData out{
80  .address = 0,
81  .command = 0,
82  };
83 
84  if (src.size() != (NBITS_DATA + NBITS_START_BIT) * 2) {
85  return {};
86  }
87 
88  // Skip start bit
89  if (!src.expect_mark(BIT_TIME_US)) {
90  return {};
91  }
92 
93  ESP_LOGVV(TAG, "%3d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", src.size(), src.peek(0),
94  src.peek(1), src.peek(2), src.peek(3), src.peek(4), src.peek(5), src.peek(6), src.peek(7), src.peek(8),
95  src.peek(9), src.peek(10), src.peek(11), src.peek(12), src.peek(13), src.peek(14), src.peek(15),
96  src.peek(16), src.peek(17), src.peek(18), src.peek(19));
97 
98  ESP_LOGVV(TAG, " %d %d %d %d %d %d", src.peek(20), src.peek(21), src.peek(22), src.peek(23), src.peek(24),
99  src.peek(25));
100 
101  // Read data bits
102  uint32_t out_data = 0;
103  int8_t bit = NBITS_DATA;
104  while (--bit >= 0) {
105  if (src.expect_space(2 * BIT_TIME_US) && src.expect_mark(BIT_TIME_US)) {
106  out_data |= 1 << bit;
107  } else if (src.expect_space(BIT_TIME_US) && src.expect_mark(2 * BIT_TIME_US)) {
108  out_data |= 0 << bit;
109  } else {
110  ESP_LOGV(TAG, "Decode ByronSX: Fail 2, %2d %08x", bit, out_data);
111  return {};
112  }
113  ESP_LOGVV(TAG, "Decode ByronSX: Data, %2d %08x", bit, out_data);
114  }
115 
116  // last bit followed by a long space
117  if (!src.peek_space_at_least(BIT_TIME_US)) {
118  ESP_LOGV(TAG, "Decode ByronSX: Fail 4 ");
119  return {};
120  }
121 
122  out.command = (uint8_t) (out_data & 0xF);
123  out_data >>= NBITS_COMMAND;
124  out.address = (uint16_t) (out_data & 0xFF);
125 
126  return out;
127 }
128 
130  ESP_LOGD(TAG, "Received ByronSX: address=0x%08X, command=0x%02x", data.address, data.command);
131 }
132 
133 } // namespace remote_base
134 } // namespace esphome
void dump(const ByronSXData &data) override
optional< ByronSXData > decode(RemoteReceiveData src) override
int32_t peek(uint32_t offset=0) const
Definition: remote_base.h:53
void encode(RemoteTransmitData *dst, const ByronSXData &data) override
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
bool peek_space_at_least(uint32_t length, uint32_t offset=0) const
Definition: remote_base.cpp:52