ESPHome 2026.5.1
Loading...
Searching...
No Matches
rc6_protocol.cpp
Go to the documentation of this file.
1#include "rc6_protocol.h"
2#include "esphome/core/log.h"
3
4namespace esphome::remote_base {
5
6static const char *const RC6_TAG = "remote.rc6";
7
8static constexpr uint16_t RC6_FREQ = 36000;
9static constexpr uint16_t RC6_UNIT = 444;
10static constexpr uint16_t RC6_HEADER_MARK = (6 * RC6_UNIT);
11static constexpr uint16_t RC6_HEADER_SPACE = (2 * RC6_UNIT);
12static constexpr uint16_t RC6_MODE_MASK = 0x07;
13
15 dst->reserve(44);
16 dst->set_carrier_frequency(RC6_FREQ);
17
18 // Encode header
19 dst->item(RC6_HEADER_MARK, RC6_HEADER_SPACE);
20
21 int32_t next{0};
22
23 // Encode startbit+mode
24 uint8_t header{static_cast<uint8_t>((1 << 3) | data.mode)};
25
26 for (uint8_t mask = 0x8; mask; mask >>= 1) {
27 if (header & mask) {
28 if (next < 0) {
29 dst->space(-next);
30 next = 0;
31 }
32 if (next >= 0) {
33 next = next + RC6_UNIT;
34 dst->mark(next);
35 next = -RC6_UNIT;
36 }
37 } else {
38 if (next > 0) {
39 dst->mark(next);
40 next = 0;
41 }
42 if (next <= 0) {
43 next = next - RC6_UNIT;
44 dst->space(-next);
45 next = RC6_UNIT;
46 }
47 }
48 }
49
50 // Toggle
51 if (data.toggle) {
52 if (next < 0) {
53 dst->space(-next);
54 next = 0;
55 }
56 if (next >= 0) {
57 next = next + RC6_UNIT * 2;
58 dst->mark(next);
59 next = -RC6_UNIT * 2;
60 }
61 } else {
62 if (next > 0) {
63 dst->mark(next);
64 next = 0;
65 }
66 if (next <= 0) {
67 next = next - RC6_UNIT * 2;
68 dst->space(-next);
69 next = RC6_UNIT * 2;
70 }
71 }
72
73 // Encode data
74 uint16_t raw{static_cast<uint16_t>((data.address << 8) | data.command)};
75
76 for (uint16_t mask = 0x8000; mask; mask >>= 1) {
77 if (raw & mask) {
78 if (next < 0) {
79 dst->space(-next);
80 next = 0;
81 }
82 if (next >= 0) {
83 next = next + RC6_UNIT;
84 dst->mark(next);
85 next = -RC6_UNIT;
86 }
87 } else {
88 if (next > 0) {
89 dst->mark(next);
90 next = 0;
91 }
92 if (next <= 0) {
93 next = next - RC6_UNIT;
94 dst->space(-next);
95 next = RC6_UNIT;
96 }
97 }
98 }
99
100 if (next > 0) {
101 dst->mark(next);
102 } else {
103 dst->space(-next);
104 }
105}
106
108 RC6Data data{
109 .mode = 0,
110 .toggle = 0,
111 .address = 0,
112 .command = 0,
113 };
114
115 // Check if header matches
116 if (!src.expect_item(RC6_HEADER_MARK, RC6_HEADER_SPACE)) {
117 return {};
118 }
119
120 uint8_t bit{1};
121 uint8_t offset{0};
122 uint8_t header{0};
123 uint32_t buffer{0};
124
125 // Startbit + mode
126 while (offset < 4) {
127 bit = src.peek() > 0;
128 header = header + (bit << (3 - offset++));
129 src.advance();
130
131 if (src.peek_mark(RC6_UNIT) || src.peek_space(RC6_UNIT)) {
132 src.advance();
133 } else if (offset == 4) {
134 break;
135 } else if (!src.peek_mark(RC6_UNIT * 2) && !src.peek_space(RC6_UNIT * 2)) {
136 return {};
137 }
138 }
139
140 data.mode = header & RC6_MODE_MASK;
141
142 if (data.mode != 0) {
143 return {}; // I dont have a device to test other modes
144 }
145
146 // Toggle
147 data.toggle = src.peek() > 0;
148 src.advance();
149 if (src.peek_mark(RC6_UNIT * 2) || src.peek_space(RC6_UNIT * 2)) {
150 src.advance();
151 }
152
153 // Data
154 offset = 0;
155 while (offset < 16) {
156 bit = src.peek() > 0;
157 buffer = buffer + (bit << (15 - offset++));
158 src.advance();
159
160 if (offset == 16) {
161 break;
162 } else if (src.peek_mark(RC6_UNIT) || src.peek_space(RC6_UNIT)) {
163 src.advance();
164 } else if (!src.peek_mark(RC6_UNIT * 2) && !src.peek_space(RC6_UNIT * 2)) {
165 return {};
166 }
167 }
168
169 data.address = (0xFF00 & buffer) >> 8;
170 data.command = (0x00FF & buffer);
171 return data;
172}
173
174void RC6Protocol::dump(const RC6Data &data) {
175 ESP_LOGI(RC6_TAG, "Received RC6: mode=0x%X, address=0x%02X, command=0x%02X, toggle=0x%X", data.mode, data.address,
176 data.command, data.toggle);
177}
178
179} // namespace esphome::remote_base
uint8_t raw[35]
Definition bl0939.h:0
void encode(RemoteTransmitData *dst, const RC6Data &data) override
void dump(const RC6Data &data) override
optional< RC6Data > decode(RemoteReceiveData src) override
bool expect_item(uint32_t mark, uint32_t space)
bool peek_space(uint32_t length, uint32_t offset=0) const
int32_t peek(uint32_t offset=0) const
Definition remote_base.h:63
bool peek_mark(uint32_t length, uint32_t offset=0) const
void set_carrier_frequency(uint32_t carrier_frequency)
Definition remote_base.h:29
void item(uint32_t mark, uint32_t space)
Definition remote_base.h:24
static void uint32_t