ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
cc1101.cpp
Go to the documentation of this file.
1#include "cc1101.h"
2#include "cc1101pa.h"
4#include "esphome/core/log.h"
5#include <cmath>
6#include <cstring>
7
8#ifdef USE_ESP32
9#include <esp_memory_utils.h>
10#endif
11
12namespace esphome::cc1101 {
13
14ESPHOME_LOG_TAG(TAG, "cc1101");
15static constexpr size_t TX_FIFO_SIZE = 64;
16
17static void split_float(float value, int mbits, uint8_t &e, uint32_t &m) {
18 int e_tmp;
19 float m_tmp = std::frexp(value, &e_tmp);
20 if (e_tmp <= mbits) {
21 e = 0;
22 m = 0;
23 return;
24 }
25 e = static_cast<uint8_t>(e_tmp - mbits - 1);
26 m = static_cast<uint32_t>(((m_tmp * 2 - 1) * (1 << (mbits + 1))) + 1) >> 1;
27 if (m == (1UL << mbits)) {
28 e = e + 1;
29 m = 0;
30 }
31}
32
34 // Datasheet defaults
35 memset(&this->state_, 0, sizeof(this->state_));
36 this->state_.GDO2_CFG = 0x0D; // Serial Data (for RX on GDO2)
37 this->state_.GDO1_CFG = 0x2E;
38 this->state_.GDO0_CFG = 0x0D; // Serial Data (for RX on GDO0 / TX Input)
39 this->state_.FIFO_THR = 7;
40 this->state_.SYNC1 = 0xD3;
41 this->state_.SYNC0 = 0x91;
42 this->state_.PKTLEN = 0xFF;
43 this->state_.APPEND_STATUS = 1;
44 this->state_.LENGTH_CONFIG = 1;
45 this->state_.CRC_EN = 1;
46 this->state_.WHITE_DATA = 1;
47 this->state_.FREQ_IF = 0x0F;
48 this->state_.FREQ2 = 0x1E;
49 this->state_.FREQ1 = 0xC4;
50 this->state_.FREQ0 = 0xEC;
51 this->state_.DRATE_E = 0x0C;
52 this->state_.CHANBW_E = 0x02;
53 this->state_.DRATE_M = 0x22;
54 this->state_.SYNC_MODE = 2;
55 this->state_.CHANSPC_E = 2;
56 this->state_.NUM_PREAMBLE = 2;
57 this->state_.CHANSPC_M = 0xF8;
58 this->state_.DEVIATION_M = 7;
59 this->state_.DEVIATION_E = 4;
60 this->state_.RX_TIME = 7;
61 this->state_.CCA_MODE = 3;
62 this->state_.PO_TIMEOUT = 1;
63 this->state_.FOC_LIMIT = 2;
64 this->state_.FOC_POST_K = 1;
65 this->state_.FOC_PRE_K = 2;
66 this->state_.FOC_BS_CS_GATE = 1;
67 this->state_.BS_POST_KP = 1;
68 this->state_.BS_POST_KI = 1;
69 this->state_.BS_PRE_KP = 2;
70 this->state_.BS_PRE_KI = 1;
71 this->state_.MAGN_TARGET = 3;
72 this->state_.AGC_LNA_PRIORITY = 1;
73 this->state_.FILTER_LENGTH = 1;
74 this->state_.WAIT_TIME = 1;
75 this->state_.HYST_LEVEL = 2;
76 this->state_.WOREVT1 = 0x87;
77 this->state_.WOREVT0 = 0x6B;
78 this->state_.RC_CAL = 1;
79 this->state_.EVENT1 = 7;
80 this->state_.RC_PD = 1;
81 this->state_.MIX_CURRENT = 2;
82 this->state_.LODIV_BUF_CURRENT_RX = 1;
83 this->state_.LNA2MIX_CURRENT = 1;
84 this->state_.LNA_CURRENT = 1;
85 this->state_.LODIV_BUF_CURRENT_TX = 1;
86 this->state_.FSCAL3_LO = 9;
87 this->state_.CHP_CURR_CAL_EN = 2;
88 this->state_.FSCAL3_HI = 2;
89 this->state_.FSCAL2 = 0x0A;
90 this->state_.FSCAL1 = 0x20;
91 this->state_.FSCAL0 = 0x0D;
92 this->state_.RCCTRL1 = 0x41;
93 this->state_.FSTEST = 0x59;
94 this->state_.PTEST = 0x7F;
95 this->state_.AGCTEST = 0x3F;
96 this->state_.TEST2 = 0x88;
97 this->state_.TEST1 = 0x31;
98 this->state_.TEST0_LO = 1;
99 this->state_.VCO_SEL_CAL_EN = 1;
100 this->state_.TEST0_HI = 2;
101
102 // PKTCTRL0
103 this->state_.PKT_FORMAT = 3;
104 this->state_.LENGTH_CONFIG = 2;
105 this->state_.FS_AUTOCAL = 1;
106
107 // CRITICAL: Initialize PA Table to avoid transmitting 0 power (Silence)
108 memset(this->pa_table_, 0, sizeof(this->pa_table_));
109}
110
112
114 this->spi_setup();
115
116 if (this->gdo0_pin_ != nullptr) {
117 this->gdo0_pin_->setup();
118 }
119
120 this->configure();
121 if (this->is_failed()) {
122 return;
123 }
124
125 // Defer pin mode setup until after all components have completed setup()
126 // This handles the case where remote_transmitter runs after CC1101 and changes pin mode
127 if (this->gdo0_pin_ != nullptr) {
128 this->defer([this]() {
130 if (this->state_.PKT_FORMAT == static_cast<uint8_t>(PacketFormat::PACKET_FORMAT_FIFO)) {
132 }
133 });
134 }
135}
136
138 // Manual reset sequence per CC1101 datasheet section 19.1.2
139 this->cs_->digital_write(true);
141 this->cs_->digital_write(false);
143 this->cs_->digital_write(true);
145 this->cs_->digital_write(false);
146 delay(5);
147
148 this->strobe_(Command::RES);
149 delay(5);
150
153 this->chip_id_ = encode_uint16(this->state_.PARTNUM, this->state_.VERSION);
154 ESP_LOGD(TAG, "CC1101 found! Chip ID: 0x%04X", this->chip_id_);
155 if (this->state_.VERSION == 0 || this->state_.PARTNUM == 0xFF) {
156 ESP_LOGE(TAG, "Failed to verify CC1101.");
157 this->mark_failed();
158 return;
159 }
160
161 this->initialized_ = true;
162
163 for (uint8_t i = 0; i <= static_cast<uint8_t>(Register::TEST0); i++) {
164 if (i == static_cast<uint8_t>(Register::FSTEST) || i == static_cast<uint8_t>(Register::AGCTEST)) {
165 continue;
166 }
167 this->write_(static_cast<Register>(i));
168 }
170
171 if (!this->enter_rx_()) {
172 this->mark_failed();
173 return;
174 }
175}
176
177void CC1101Component::call_listeners_(const std::vector<uint8_t> &packet, float freq_offset, float rssi, uint8_t lqi) {
178 for (auto &listener : this->listeners_) {
179 listener->on_packet(packet, freq_offset, rssi, lqi);
180 }
181 this->packet_trigger_.trigger(packet, freq_offset, rssi, lqi);
182}
183
185 this->disable_loop();
186 if (this->state_.PKT_FORMAT != static_cast<uint8_t>(PacketFormat::PACKET_FORMAT_FIFO) || this->gdo0_pin_ == nullptr ||
187 !this->gdo0_pin_->digital_read()) {
188 return;
189 }
190
191 // Read state
193 uint8_t rx_bytes = this->state_.NUM_RXBYTES;
194 bool overflow = this->state_.RXFIFO_OVERFLOW;
195 if (overflow || rx_bytes == 0) {
196 ESP_LOGW(TAG, "RX FIFO overflow, flushing");
197 this->enter_idle_();
198 this->strobe_(Command::FRX);
199 this->enter_rx_();
200 return;
201 }
202
203 // Read packet
204 uint8_t payload_length, expected_rx;
205 if (this->state_.LENGTH_CONFIG == static_cast<uint8_t>(LengthConfig::LENGTH_CONFIG_VARIABLE)) {
206 this->read_(Register::FIFO, &payload_length, 1);
207 expected_rx = payload_length + 1;
208 } else {
209 payload_length = this->state_.PKTLEN;
210 expected_rx = payload_length;
211 }
212 if (payload_length == 0 || payload_length > 64 || rx_bytes != expected_rx) {
213 ESP_LOGW(TAG, "Invalid packet: rx_bytes %u, payload_length %u", rx_bytes, payload_length);
214 this->enter_idle_();
215 this->strobe_(Command::FRX);
216 this->enter_rx_();
217 return;
218 }
219 this->packet_.resize(payload_length);
220 this->read_(Register::FIFO, this->packet_.data(), payload_length);
221
222 // Read status from registers (more reliable than FIFO status bytes due to timing issues)
224 this->read_(Register::RSSI);
225 this->read_(Register::LQI);
226 float freq_offset = static_cast<int8_t>(this->state_.FREQEST) * (XTAL_FREQUENCY / (1 << 14));
227 float rssi = (this->state_.RSSI * RSSI_STEP) - RSSI_OFFSET;
228 bool crc_ok = (this->state_.LQI & STATUS_CRC_OK_MASK) != 0;
229 uint8_t lqi = this->state_.LQI & STATUS_LQI_MASK;
230 if (this->state_.CRC_EN == 0 || crc_ok) {
231 this->call_listeners_(this->packet_, freq_offset, rssi, lqi);
232 }
233
234 // Return to rx
235 this->enter_idle_();
236 this->strobe_(Command::FRX);
237 this->enter_rx_();
238}
239
241 static const char *const MODULATION_NAMES[] = {"2-FSK", "GFSK", "UNUSED", "ASK/OOK",
242 "4-FSK", "UNUSED", "UNUSED", "MSK"};
243 int32_t freq = static_cast<int32_t>(this->state_.FREQ2 << 16 | this->state_.FREQ1 << 8 | this->state_.FREQ0) *
244 XTAL_FREQUENCY / (1 << 16);
245 float symbol_rate = (((256.0f + this->state_.DRATE_M) * (1 << this->state_.DRATE_E)) / (1 << 28)) * XTAL_FREQUENCY;
246 float bw = XTAL_FREQUENCY / (8.0f * (4 + this->state_.CHANBW_M) * (1 << this->state_.CHANBW_E));
247 ESP_LOGCONFIG(TAG,
248 "CC1101:\n"
249 " Chip ID: 0x%04X\n"
250 " Frequency: %" PRId32 " Hz\n"
251 " Channel: %u\n"
252 " Modulation: %s\n"
253 " Symbol Rate: %.0f baud\n"
254 " Filter Bandwidth: %.1f Hz\n"
255 " Output Power: %.1f dBm",
256 this->chip_id_, freq, this->state_.CHANNR, MODULATION_NAMES[this->state_.MOD_FORMAT & 0x07],
257 symbol_rate, bw, this->output_power_effective_);
258 LOG_PIN(" CS Pin: ", this->cs_);
259}
260
262 // Read the mode before the PKTCTRL0 write below overwrites it in state_
263 const bool packet_mode = this->state_.PKT_FORMAT == static_cast<uint8_t>(PacketFormat::PACKET_FORMAT_FIFO);
264 // Ensure Packet Format is 3 (Async Serial)
265 this->write_(Register::PKTCTRL0, 0x32);
266 ESP_LOGV(TAG, "Beginning TX sequence");
267 if (this->gdo0_pin_ != nullptr) {
268 // setup() only attaches the interrupt in packet mode. In async serial mode the pin may be
269 // shared with remote_receiver, and detaching here would remove the receiver's interrupt.
270 if (packet_mode) {
272 }
274 }
275 // Transition through IDLE to bypass CCA (Clear Channel Assessment) which can
276 // block TX entry when strobing from RX, and to ensure FS_AUTOCAL calibration
277 this->enter_idle_();
278 if (!this->enter_tx_()) {
279 ESP_LOGW(TAG, "Failed to enter TX state!");
280 }
281}
282
284 ESP_LOGV(TAG, "Beginning RX sequence");
285 if (this->gdo0_pin_ != nullptr) {
287 }
288 // Transition through IDLE to ensure FS_AUTOCAL calibration occurs
289 this->enter_idle_();
290 if (!this->enter_rx_()) {
291 ESP_LOGW(TAG, "Failed to enter RX state!");
292 }
293}
294
296 this->strobe_(Command::RES);
297 this->configure();
298}
299
301 ESP_LOGV(TAG, "Setting IDLE state");
302 this->enter_idle_();
303}
304
305bool CC1101Component::wait_for_state_(State target_state, uint32_t timeout_ms) {
306 uint32_t start = millis();
307 while (millis() - start < timeout_ms) {
309 State s = static_cast<State>(this->state_.MARC_STATE);
310 if (s == target_state) {
311 return true;
312 }
314 }
315 return false;
316}
317
319 // The PLL must be recalibrated until PLL lock is achieved
320 for (uint8_t retries = PLL_LOCK_RETRIES; retries > 0; retries--) {
321 this->strobe_(cmd);
322 if (!this->wait_for_state_(target_state)) {
323 return false;
324 }
325 this->read_(Register::FSCAL1);
326 if (this->state_.FSCAL1 != FSCAL1_PLL_NOT_LOCKED) {
327 return true;
328 }
329 ESP_LOGW(TAG, "PLL lock failed, retrying calibration");
330 this->enter_idle_();
331 }
332 ESP_LOGE(TAG, "PLL lock failed after retries");
333 return false;
334}
335
340
342
344
346 uint8_t index = static_cast<uint8_t>(cmd);
347 if (cmd < Command::RES || cmd > Command::NOP) {
348 return 0xFF;
349 }
350 this->enable();
351 uint8_t status_byte = this->transfer_byte(index);
352 this->disable();
353 return status_byte;
354}
355
357 uint8_t index = static_cast<uint8_t>(reg);
358 this->enable();
359 this->write_byte(index);
360 this->write_array(&this->state_.regs()[index], 1);
361 this->disable();
362}
363
364void CC1101Component::write_(Register reg, uint8_t value) {
365 uint8_t index = static_cast<uint8_t>(reg);
366 this->state_.regs()[index] = value;
367 this->write_(reg);
368}
369
370void CC1101Component::write_(Register reg, const uint8_t *buffer, size_t length) {
371 uint8_t index = static_cast<uint8_t>(reg);
372 this->enable();
373 this->write_byte(index | BUS_WRITE | BUS_BURST);
374 this->write_array(buffer, length);
375 this->disable();
376}
377
379 uint8_t index = static_cast<uint8_t>(reg);
380 this->enable();
381 this->write_byte(index | BUS_READ | BUS_BURST);
382 this->state_.regs()[index] = this->transfer_byte(0);
383 this->disable();
384}
385
386void CC1101Component::read_(Register reg, uint8_t *buffer, size_t length) {
387 uint8_t index = static_cast<uint8_t>(reg);
388 this->enable();
389 this->write_byte(index | BUS_READ | BUS_BURST);
390 this->read_array(buffer, length);
391 this->disable();
392}
393
395 if (this->state_.PKT_FORMAT != static_cast<uint8_t>(PacketFormat::PACKET_FORMAT_FIFO)) {
396 return CC1101Error::PARAMS;
397 }
398 const bool variable = this->state_.LENGTH_CONFIG == static_cast<uint8_t>(LengthConfig::LENGTH_CONFIG_VARIABLE);
399 // In variable length mode the FIFO also holds the length byte
400 if (len + (variable ? 1 : 0) > TX_FIFO_SIZE) {
401 ESP_LOGE(TAG, "Packet of %u bytes does not fit the TX FIFO", static_cast<unsigned>(len));
402 return CC1101Error::PARAMS;
403 }
404
405 // Write packet
406 this->enter_idle_();
407 this->strobe_(Command::FTX);
408 if (variable) {
409 this->write_(Register::FIFO, static_cast<uint8_t>(len));
410 }
411#ifdef USE_ESP32
412 // SPI DMA cannot read flash or unaligned buffers; stage them here so the driver does not allocate a copy
413 alignas(4) uint8_t staged[TX_FIFO_SIZE];
414 if (len != 0 && (!esp_ptr_dma_capable(data) || (reinterpret_cast<uintptr_t>(data) & 3) != 0)) {
415 std::memcpy(staged, data, len);
416 data = staged;
417 }
418#endif
419 this->write_(Register::FIFO, data, len);
420
421 // Calibrate PLL
423 ESP_LOGW(TAG, "PLL lock failed during TX");
424 this->enter_idle_();
425 this->enter_rx_();
427 }
428
429 // Transmit packet
430 this->strobe_(Command::TX);
431 if (!this->wait_for_state_(State::IDLE, 1000)) {
432 ESP_LOGW(TAG, "TX timeout");
433 this->enter_idle_();
434 this->enter_rx_();
436 }
437
438 // Return to rx
439 this->enter_rx_();
440 return CC1101Error::NONE;
441}
442
443// Setters
445 this->output_power_requested_ = value;
446 int32_t freq = static_cast<int32_t>(this->state_.FREQ2 << 16 | this->state_.FREQ1 << 8 | this->state_.FREQ0) *
447 XTAL_FREQUENCY / (1 << 16);
448 uint8_t a = 0xC0;
449 if (freq >= 300000000 && freq <= 348000000) {
450 a = PowerTableItem::find(PA_TABLE_315, sizeof(PA_TABLE_315) / sizeof(PA_TABLE_315[0]), value);
451 } else if (freq >= 378000000 && freq <= 464000000) {
452 a = PowerTableItem::find(PA_TABLE_433, sizeof(PA_TABLE_433) / sizeof(PA_TABLE_433[0]), value);
453 } else if (freq >= 779000000 && freq < 900000000) {
454 a = PowerTableItem::find(PA_TABLE_868, sizeof(PA_TABLE_868) / sizeof(PA_TABLE_868[0]), value);
455 } else if (freq >= 900000000 && freq <= 928000000) {
456 a = PowerTableItem::find(PA_TABLE_915, sizeof(PA_TABLE_915) / sizeof(PA_TABLE_915[0]), value);
457 }
458
459 if (static_cast<Modulation>(this->state_.MOD_FORMAT) == Modulation::MODULATION_ASK_OOK) {
460 this->pa_table_[0] = 0;
461 this->pa_table_[1] = a;
462 } else {
463 this->pa_table_[0] = a;
464 this->pa_table_[1] = 0;
465 }
466 this->output_power_effective_ = value;
467 if (this->initialized_) {
468 this->write_(Register::PATABLE, this->pa_table_, sizeof(this->pa_table_));
469 }
470}
471
473 this->state_.CLOSE_IN_RX = static_cast<uint8_t>(value);
474 if (this->initialized_) {
476 }
477}
478
480 this->state_.DEM_DCFILT_OFF = value ? 0 : 1;
481 if (this->initialized_) {
483 }
484}
485
487 int32_t freq = static_cast<int32_t>(value * (1 << 16) / XTAL_FREQUENCY);
488 this->state_.FREQ2 = static_cast<uint8_t>(freq >> 16);
489 this->state_.FREQ1 = static_cast<uint8_t>(freq >> 8);
490 this->state_.FREQ0 = static_cast<uint8_t>(freq);
491 if (this->initialized_) {
492 this->enter_idle_();
493 this->write_(Register::FREQ2);
494 this->write_(Register::FREQ1);
495 this->write_(Register::FREQ0);
496 this->enter_rx_();
497 }
498}
499
501 this->state_.FREQ_IF = value * (1 << 10) / XTAL_FREQUENCY;
502 if (this->initialized_) {
504 }
505}
506
508 uint8_t e;
509 uint32_t m;
510 split_float(XTAL_FREQUENCY / (value * 8), 2, e, m);
511 this->state_.CHANBW_E = e;
512 this->state_.CHANBW_M = static_cast<uint8_t>(m);
513 if (this->initialized_) {
515 }
516}
517
518void CC1101Component::set_channel(uint8_t value) {
519 this->state_.CHANNR = value;
520 if (this->initialized_) {
521 this->enter_idle_();
523 this->enter_rx_();
524 }
525}
526
528 uint8_t e;
529 uint32_t m;
530 split_float(value * (1 << 18) / XTAL_FREQUENCY, 8, e, m);
531 this->state_.CHANSPC_E = e;
532 this->state_.CHANSPC_M = static_cast<uint8_t>(m);
533 if (this->initialized_) {
536 }
537}
538
540 uint8_t e;
541 uint32_t m;
542 split_float(value * (1 << 17) / XTAL_FREQUENCY, 3, e, m);
543 this->state_.DEVIATION_E = e;
544 this->state_.DEVIATION_M = static_cast<uint8_t>(m);
545 if (this->initialized_) {
547 }
548}
549
551 this->state_.DEVIATION_E = 0;
552 this->state_.DEVIATION_M = value - 1;
553 if (this->initialized_) {
555 }
556}
557
559 uint8_t e;
560 uint32_t m;
561 split_float(value * (1 << 28) / XTAL_FREQUENCY, 8, e, m);
562 this->state_.DRATE_E = e;
563 this->state_.DRATE_M = static_cast<uint8_t>(m);
564 if (this->initialized_) {
567 }
568}
569
571 this->state_.SYNC_MODE = static_cast<uint8_t>(value);
572 if (this->initialized_) {
574 }
575}
576
578 this->state_.CARRIER_SENSE_ABOVE_THRESHOLD = value ? 1 : 0;
579 if (this->initialized_) {
581 }
582}
583
585 this->state_.MOD_FORMAT = static_cast<uint8_t>(value);
586 this->state_.PA_POWER = value == Modulation::MODULATION_ASK_OOK ? 1 : 0;
587 if (this->initialized_) {
588 this->enter_idle_();
592 this->enter_rx_();
593 }
594}
595
597 this->state_.MANCHESTER_EN = value ? 1 : 0;
598 if (this->initialized_) {
600 }
601}
602
604 this->state_.NUM_PREAMBLE = value;
605 if (this->initialized_) {
607 }
608}
609
610void CC1101Component::set_sync1(uint8_t value) {
611 this->state_.SYNC1 = value;
612 if (this->initialized_) {
613 this->write_(Register::SYNC1);
614 }
615}
616
617void CC1101Component::set_sync0(uint8_t value) {
618 this->state_.SYNC0 = value;
619 if (this->initialized_) {
620 this->write_(Register::SYNC0);
621 }
622}
623
625 this->state_.MAGN_TARGET = static_cast<uint8_t>(value);
626 if (this->initialized_) {
628 }
629}
630
632 this->state_.MAX_LNA_GAIN = static_cast<uint8_t>(value);
633 if (this->initialized_) {
635 }
636}
637
639 this->state_.MAX_DVGA_GAIN = static_cast<uint8_t>(value);
640 if (this->initialized_) {
642 }
643}
644
646 this->state_.CARRIER_SENSE_ABS_THR = static_cast<uint8_t>(value & 0b1111);
647 if (this->initialized_) {
649 }
650}
651
653 this->state_.CARRIER_SENSE_REL_THR = static_cast<uint8_t>(value);
654 if (this->initialized_) {
656 }
657}
658
660 this->state_.AGC_LNA_PRIORITY = value ? 1 : 0;
661 if (this->initialized_) {
663 }
664}
665
667 this->state_.FILTER_LENGTH = static_cast<uint8_t>(value);
668 if (this->initialized_) {
670 }
671}
672
674 this->state_.FILTER_LENGTH = static_cast<uint8_t>(value);
675 if (this->initialized_) {
677 }
678}
679
681 this->state_.AGC_FREEZE = static_cast<uint8_t>(value);
682 if (this->initialized_) {
684 }
685}
686
688 this->state_.WAIT_TIME = static_cast<uint8_t>(value);
689 if (this->initialized_) {
691 }
692}
693
695 this->state_.HYST_LEVEL = static_cast<uint8_t>(value);
696 if (this->initialized_) {
698 }
699}
700
702 this->state_.FOC_BS_CS_GATE = value ? 1 : 0;
703 if (this->initialized_) {
705 }
706}
707
709 this->state_.FOC_LIMIT = static_cast<uint8_t>(value);
710 if (this->initialized_) {
712 }
713}
714
716 this->state_.FOC_PRE_K = static_cast<uint8_t>(value);
717 if (this->initialized_) {
719 }
720}
721
723 this->state_.FOC_POST_K = static_cast<uint8_t>(value);
724 if (this->initialized_) {
726 }
727}
728
730 this->state_.BS_LIMIT = static_cast<uint8_t>(value);
731 if (this->initialized_) {
732 this->write_(Register::BSCFG);
733 }
734}
735
737 this->state_.BS_PRE_KI = static_cast<uint8_t>(value);
738 if (this->initialized_) {
739 this->write_(Register::BSCFG);
740 }
741}
742
744 this->state_.BS_PRE_KP = static_cast<uint8_t>(value);
745 if (this->initialized_) {
746 this->write_(Register::BSCFG);
747 }
748}
749
751 this->state_.BS_POST_KI = static_cast<uint8_t>(value);
752 if (this->initialized_) {
753 this->write_(Register::BSCFG);
754 }
755}
756
758 this->state_.BS_POST_KP = static_cast<uint8_t>(value);
759 if (this->initialized_) {
760 this->write_(Register::BSCFG);
761 }
762}
763
765 this->state_.PKT_FORMAT =
767 if (value) {
768 // Configure GDO0 for FIFO status (asserts on RX FIFO threshold or end of packet)
769 this->state_.GDO0_CFG = 0x01;
770 // Set max RX FIFO threshold to ensure we only trigger on end-of-packet
771 this->state_.FIFO_THR = 15;
772 // Don't append status bytes to FIFO - we read from registers instead
773 this->state_.APPEND_STATUS = 0;
774 } else {
775 // Configure GDO0 for serial data (async serial mode)
776 this->state_.GDO0_CFG = 0x0D;
777 }
778 if (this->initialized_) {
779 if (this->gdo0_pin_ != nullptr) {
780 if (value) {
782 } else {
784 }
785 }
790 }
791}
792
794 if (value == 0) {
795 this->state_.LENGTH_CONFIG = static_cast<uint8_t>(LengthConfig::LENGTH_CONFIG_VARIABLE);
796 } else {
797 this->state_.LENGTH_CONFIG = static_cast<uint8_t>(LengthConfig::LENGTH_CONFIG_FIXED);
798 this->state_.PKTLEN = value;
799 }
800 if (this->initialized_) {
803 }
804}
805
807 this->state_.CRC_EN = value ? 1 : 0;
808 if (this->initialized_) {
810 }
811}
812
814 this->state_.WHITE_DATA = value ? 1 : 0;
815 if (this->initialized_) {
817 }
818}
819
820} // namespace esphome::cc1101
uint8_t m
Definition bl0906.h:1
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:274
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
void disable_loop()
Disable this component's loop.
virtual void digital_write(bool value)=0
void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE
Inform the parent automation that the event has triggered.
Definition automation.h:533
void set_bs_post_kp(BsPostKp value)
Definition cc1101.cpp:757
void set_packet_mode(bool value)
Definition cc1101.cpp:764
void set_max_dvga_gain(MaxDvgaGain value)
Definition cc1101.cpp:638
void set_whitening(bool value)
Definition cc1101.cpp:813
void set_carrier_sense_above_threshold(bool value)
Definition cc1101.cpp:577
void write_(Register reg)
Definition cc1101.cpp:356
void set_sync0(uint8_t value)
Definition cc1101.cpp:617
void set_freeze(Freeze value)
Definition cc1101.cpp:680
void call_listeners_(const std::vector< uint8_t > &packet, float freq_offset, float rssi, uint8_t lqi)
Definition cc1101.cpp:177
void set_rx_attenuation(RxAttenuation value)
Definition cc1101.cpp:472
InternalGPIOPin * gdo0_pin_
Definition cc1101.h:110
void set_symbol_rate(float value)
Definition cc1101.cpp:558
void set_bs_pre_ki(BsPreKi value)
Definition cc1101.cpp:736
uint8_t strobe_(Command cmd)
Definition cc1101.cpp:345
void set_sync_mode(SyncMode value)
Definition cc1101.cpp:570
void set_fsk_deviation(float value)
Definition cc1101.cpp:539
void set_bs_pre_kp(BsPreKp value)
Definition cc1101.cpp:743
void set_msk_deviation(uint8_t value)
Definition cc1101.cpp:550
void set_carrier_sense_rel_thr(CarrierSenseRelThr value)
Definition cc1101.cpp:652
uint8_t pa_table_[PA_TABLE_SIZE]
Definition cc1101.h:105
void set_lna_priority(bool value)
Definition cc1101.cpp:659
void set_foc_bs_cs_gate(bool value)
Definition cc1101.cpp:701
void set_foc_pre_k(FocPreK value)
Definition cc1101.cpp:715
void set_output_power(float value)
Definition cc1101.cpp:444
void set_modulation_type(Modulation value)
Definition cc1101.cpp:584
void set_if_frequency(float value)
Definition cc1101.cpp:500
void set_frequency(float value)
Definition cc1101.cpp:486
void set_num_preamble(uint8_t value)
Definition cc1101.cpp:603
void set_hyst_level(HystLevel value)
Definition cc1101.cpp:694
void set_filter_bandwidth(float value)
Definition cc1101.cpp:507
void set_filter_length_fsk_msk(FilterLengthFskMsk value)
Definition cc1101.cpp:666
void set_crc_enable(bool value)
Definition cc1101.cpp:806
static void IRAM_ATTR gpio_intr(CC1101Component *arg)
Definition cc1101.cpp:111
void set_carrier_sense_abs_thr(int8_t value)
Definition cc1101.cpp:645
void set_bs_post_ki(BsPostKi value)
Definition cc1101.cpp:750
bool enter_calibrated_(State target_state, Command cmd)
Definition cc1101.cpp:318
void set_magn_target(MagnTarget value)
Definition cc1101.cpp:624
void set_channel_spacing(float value)
Definition cc1101.cpp:527
CC1101Error transmit_packet(const std::vector< uint8_t > &packet)
Definition cc1101.h:92
void set_wait_time(WaitTime value)
Definition cc1101.cpp:687
std::vector< CC1101Listener * > listeners_
Definition cc1101.h:117
void set_dc_blocking_filter(bool value)
Definition cc1101.cpp:479
void set_packet_length(uint8_t value)
Definition cc1101.cpp:793
void set_manchester(bool value)
Definition cc1101.cpp:596
std::vector< uint8_t > packet_
Definition cc1101.h:116
void set_channel(uint8_t value)
Definition cc1101.cpp:518
void set_foc_limit(FocLimit value)
Definition cc1101.cpp:708
void set_filter_length_ask_ook(FilterLengthAskOok value)
Definition cc1101.cpp:673
void set_max_lna_gain(MaxLnaGain value)
Definition cc1101.cpp:631
void set_sync1(uint8_t value)
Definition cc1101.cpp:610
bool wait_for_state_(State target_state, uint32_t timeout_ms=100)
Definition cc1101.cpp:305
void set_bs_limit(BsLimit value)
Definition cc1101.cpp:729
void set_foc_post_k(FocPostK value)
Definition cc1101.cpp:722
Trigger< std::vector< uint8_t >, float, float, uint8_t > packet_trigger_
Definition cc1101.h:115
void attach_interrupt(void(*func)(T *), T *arg, gpio::InterruptType type) const
Definition gpio.h:29
void pin_mode(gpio::Flags flags) override
Definition gpio.cpp:188
uint32_t buffer
Definition gif.cpp:50
ESPHOME_LOG_TAG(TAG, "cc1101")
@ INTERRUPT_RISING_EDGE
Definition gpio_pin.h:52
const void size_t len
Definition hal.h:68
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
Definition hal.cpp:48
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:980
void HOT delay(uint32_t ms)
Definition hal.cpp:85
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:25
static void uint32_t
static uint8_t find(const PowerTableItem *items, size_t count, float &dbm_target)
Definition cc1101pa.h:15
uint16_t length
Definition tt21100.cpp:0