diff --git a/esphome/components/cc1101/cc1101.cpp b/esphome/components/cc1101/cc1101.cpp index 7e5309e1659..fe9238b1411 100644 --- a/esphome/components/cc1101/cc1101.cpp +++ b/esphome/components/cc1101/cc1101.cpp @@ -140,7 +140,10 @@ void CC1101Component::setup() { this->write_(static_cast(i)); } this->set_output_power(this->output_power_requested_); - this->strobe_(Command::RX); + if (!this->enter_rx_()) { + this->mark_failed(); + return; + } // Defer pin mode setup until after all components have completed setup() // This handles the case where remote_transmitter runs after CC1101 and changes pin mode @@ -163,8 +166,7 @@ void CC1101Component::loop() { ESP_LOGW(TAG, "RX FIFO overflow, flushing"); this->enter_idle_(); this->strobe_(Command::FRX); - this->strobe_(Command::RX); - this->wait_for_state_(State::RX); + this->enter_rx_(); return; } @@ -181,8 +183,7 @@ void CC1101Component::loop() { ESP_LOGW(TAG, "Invalid packet: rx_bytes %u, payload_length %u", rx_bytes, payload_length); this->enter_idle_(); this->strobe_(Command::FRX); - this->strobe_(Command::RX); - this->wait_for_state_(State::RX); + this->enter_rx_(); return; } this->packet_.resize(payload_length); @@ -201,8 +202,7 @@ void CC1101Component::loop() { // Return to rx this->enter_idle_(); this->strobe_(Command::FRX); - this->strobe_(Command::RX); - this->wait_for_state_(State::RX); + this->enter_rx_(); } void CC1101Component::dump_config() { @@ -233,9 +233,8 @@ void CC1101Component::begin_tx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_OUTPUT); } - this->strobe_(Command::TX); - if (!this->wait_for_state_(State::TX, 50)) { - ESP_LOGW(TAG, "Timed out waiting for TX state!"); + if (!this->enter_tx_()) { + ESP_LOGW(TAG, "Failed to enter TX state!"); } } @@ -244,7 +243,9 @@ void CC1101Component::begin_rx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_INPUT); } - this->strobe_(Command::RX); + if (!this->enter_rx_()) { + ESP_LOGW(TAG, "Failed to enter RX state!"); + } } void CC1101Component::reset() { @@ -270,11 +271,33 @@ bool CC1101Component::wait_for_state_(State target_state, uint32_t timeout_ms) { return false; } +bool CC1101Component::enter_calibrated_(State target_state, Command cmd) { + // The PLL must be recalibrated until PLL lock is achieved + for (uint8_t retries = PLL_LOCK_RETRIES; retries > 0; retries--) { + this->strobe_(cmd); + if (!this->wait_for_state_(target_state)) { + return false; + } + this->read_(Register::FSCAL1); + if (this->state_.FSCAL1 != FSCAL1_PLL_NOT_LOCKED) { + return true; + } + ESP_LOGW(TAG, "PLL lock failed, retrying calibration"); + this->enter_idle_(); + } + ESP_LOGE(TAG, "PLL lock failed after retries"); + return false; +} + void CC1101Component::enter_idle_() { this->strobe_(Command::IDLE); this->wait_for_state_(State::IDLE); } +bool CC1101Component::enter_rx_() { return this->enter_calibrated_(State::RX, Command::RX); } + +bool CC1101Component::enter_tx_() { return this->enter_calibrated_(State::TX, Command::TX); } + uint8_t CC1101Component::strobe_(Command cmd) { uint8_t index = static_cast(cmd); if (cmd < Command::RES || cmd > Command::NOP) { @@ -336,18 +359,26 @@ CC1101Error CC1101Component::transmit_packet(const std::vector &packet) this->write_(Register::FIFO, static_cast(packet.size())); } this->write_(Register::FIFO, packet.data(), packet.size()); + + // Calibrate PLL + if (!this->enter_calibrated_(State::FSTXON, Command::FSTXON)) { + ESP_LOGW(TAG, "PLL lock failed during TX"); + this->enter_idle_(); + this->enter_rx_(); + return CC1101Error::PLL_LOCK; + } + + // Transmit packet this->strobe_(Command::TX); if (!this->wait_for_state_(State::IDLE, 1000)) { ESP_LOGW(TAG, "TX timeout"); this->enter_idle_(); - this->strobe_(Command::RX); - this->wait_for_state_(State::RX); + this->enter_rx_(); return CC1101Error::TIMEOUT; } // Return to rx - this->strobe_(Command::RX); - this->wait_for_state_(State::RX); + this->enter_rx_(); return CC1101Error::NONE; } @@ -404,7 +435,7 @@ void CC1101Component::set_frequency(float value) { this->write_(Register::FREQ2); this->write_(Register::FREQ1); this->write_(Register::FREQ0); - this->strobe_(Command::RX); + this->enter_rx_(); } } @@ -431,7 +462,7 @@ void CC1101Component::set_channel(uint8_t value) { if (this->initialized_) { this->enter_idle_(); this->write_(Register::CHANNR); - this->strobe_(Command::RX); + this->enter_rx_(); } } @@ -500,7 +531,7 @@ void CC1101Component::set_modulation_type(Modulation value) { this->set_output_power(this->output_power_requested_); this->write_(Register::MDMCFG2); this->write_(Register::FREND0); - this->strobe_(Command::RX); + this->enter_rx_(); } } diff --git a/esphome/components/cc1101/cc1101.h b/esphome/components/cc1101/cc1101.h index b896f7e9742..fe4898660e7 100644 --- a/esphome/components/cc1101/cc1101.h +++ b/esphome/components/cc1101/cc1101.h @@ -9,7 +9,7 @@ namespace esphome::cc1101 { -enum class CC1101Error { NONE = 0, TIMEOUT, PARAMS, CRC_ERROR, FIFO_OVERFLOW }; +enum class CC1101Error { NONE = 0, TIMEOUT, PARAMS, CRC_ERROR, FIFO_OVERFLOW, PLL_LOCK }; class CC1101Component : public Component, public spi::SPIDevice