7 namespace remote_base {
9 static const char *
const TAG =
"remote.keeloq";
11 static const uint32_t BIT_TIME_US = 380;
12 static const uint8_t NBITS_PREAMBLE = 12;
13 static const uint8_t NBITS_REPEAT = 1;
14 static const uint8_t NBITS_VLOW = 1;
15 static const uint8_t NBITS_SERIAL = 28;
16 static const uint8_t NBITS_BUTTONS = 4;
17 static const uint8_t NBITS_DISC = 12;
18 static const uint8_t NBITS_SYNC_CNT = 16;
20 static const uint8_t NBITS_FIXED_DATA = NBITS_REPEAT + NBITS_VLOW + NBITS_BUTTONS + NBITS_SERIAL;
21 static const uint8_t NBITS_ENCRYPTED_DATA = NBITS_BUTTONS + NBITS_DISC + NBITS_SYNC_CNT;
22 static const uint8_t NBITS_DATA = NBITS_FIXED_DATA + NBITS_ENCRYPTED_DATA;
37 uint32_t out_data = 0x0;
39 ESP_LOGD(TAG,
"Send Keeloq: address=%07" PRIx32
" command=%03x encrypted=%08" PRIx32, data.
address, data.
command,
41 ESP_LOGV(TAG,
"Send Keeloq: data bits (%d + %d)", NBITS_ENCRYPTED_DATA, NBITS_FIXED_DATA);
44 for (uint8_t cnt = NBITS_PREAMBLE; cnt; cnt--) {
45 dst->
space(BIT_TIME_US);
46 dst->
mark(BIT_TIME_US);
50 dst->
space(10 * BIT_TIME_US);
55 ESP_LOGV(TAG,
"Send Keeloq: Encrypted data %04" PRIx32, out_data);
57 for (uint32_t mask = 1, cnt = 0; cnt < NBITS_ENCRYPTED_DATA; cnt++, mask <<= 1) {
58 if (out_data & mask) {
59 dst->
mark(1 * BIT_TIME_US);
60 dst->
space(2 * BIT_TIME_US);
62 dst->
mark(2 * BIT_TIME_US);
63 dst->
space(1 * BIT_TIME_US);
68 out_data = (data.
command & 0x0f);
69 out_data <<= NBITS_SERIAL;
71 ESP_LOGV(TAG,
"Send Keeloq: Fixed data %04" PRIx32, out_data);
73 for (uint32_t mask = 1, cnt = 0; cnt < (NBITS_FIXED_DATA - 2); cnt++, mask <<= 1) {
74 if (out_data & mask) {
75 dst->
mark(1 * BIT_TIME_US);
76 dst->
space(2 * BIT_TIME_US);
78 dst->
mark(2 * BIT_TIME_US);
79 dst->
space(1 * BIT_TIME_US);
85 dst->
mark(1 * BIT_TIME_US);
86 dst->
space(2 * BIT_TIME_US);
88 dst->
mark(2 * BIT_TIME_US);
89 dst->
space(1 * BIT_TIME_US);
93 dst->
mark(1 * BIT_TIME_US);
94 dst->
space(2 * BIT_TIME_US);
97 dst->
space(39 * BIT_TIME_US);
110 if (src.
size() != (NBITS_PREAMBLE + NBITS_DATA) * 2) {
115 "%2" PRId32
": %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
116 " %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
" %" PRId32
117 " %" PRId32
" %" PRId32
" %" PRId32,
123 int8_t bit = NBITS_PREAMBLE - 1;
126 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 1, %d %" PRId32, bit + 1, src.
peek());
131 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 1, %d %" PRId32, bit + 1, src.
peek());
136 uint32_t out_data = 0;
137 for (bit = 0; bit < NBITS_ENCRYPTED_DATA; bit++) {
139 out_data |= 0 << bit;
141 out_data |= 1 << bit;
143 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 2, %" PRIu32
" %" PRId32, src.
get_index(), src.
peek());
147 ESP_LOGVV(TAG,
"Decode KeeLoq: Data, %d %08" PRIx32, bit, out_data);
148 out.encrypted = out_data;
152 for (bit = 0; bit < NBITS_SERIAL + NBITS_BUTTONS; bit++) {
154 out_data |= 0 << bit;
156 out_data |= 1 << bit;
158 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 3, %" PRIu32
" %" PRId32, src.
get_index(), src.
peek());
162 ESP_LOGVV(TAG,
"Decode KeeLoq: Data, %2d %08" PRIx32, bit, out_data);
163 out.command = (out_data >> 28) & 0xf;
164 out.address = out_data & 0xfffffff;
172 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 4, %" PRId32, src.
peek());
182 ESP_LOGV(TAG,
"Decode KeeLoq: Fail 5, %" PRId32, src.
peek());
190 ESP_LOGD(TAG,
"Received Keeloq: address=0x%08" PRIx32
", command=0x%02x", data.
address, data.
command);
bool expect_space(uint32_t length)
bool expect_mark(uint32_t length)
void mark(uint32_t length)
int32_t peek(uint32_t offset=0) const
uint32_t get_index() const
void dump(const KeeloqData &data) override
optional< KeeloqData > decode(RemoteReceiveData src) override
void space(uint32_t length)
Implementation of SPI Controller mode.
void encode(RemoteTransmitData *dst, const KeeloqData &data) override
bool peek_space_at_least(uint32_t length, uint32_t offset=0) const