#pragma once #include "esphome/core/component.h" #include "esphome/core/hal.h" #include "esphome/components/spi/spi.h" #include "esphome/core/automation.h" #include "cc1101defs.h" #include namespace esphome::cc1101 { enum class CC1101Error { NONE = 0, TIMEOUT, PARAMS, CRC_ERROR, FIFO_OVERFLOW, PLL_LOCK }; class CC1101Listener { public: virtual void on_packet(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi) = 0; }; class CC1101Component : public Component, public spi::SPIDevice { public: CC1101Component(); void setup() override; void loop() override; void dump_config() override; // Actions void begin_tx(); void begin_rx(); void reset(); void set_idle(); // GDO Pin Configuration void set_gdo0_pin(InternalGPIOPin *pin) { this->gdo0_pin_ = pin; } // Configuration Setters void set_output_power(float value); void set_rx_attenuation(RxAttenuation value); void set_dc_blocking_filter(bool value); // Tuner settings void set_frequency(float value); void set_if_frequency(float value); void set_filter_bandwidth(float value); void set_channel(uint8_t value); void set_channel_spacing(float value); void set_fsk_deviation(float value); void set_msk_deviation(uint8_t value); void set_symbol_rate(float value); void set_sync_mode(SyncMode value); void set_carrier_sense_above_threshold(bool value); void set_modulation_type(Modulation value); void set_manchester(bool value); void set_num_preamble(uint8_t value); void set_sync1(uint8_t value); void set_sync0(uint8_t value); // AGC settings void set_magn_target(MagnTarget value); void set_max_lna_gain(MaxLnaGain value); void set_max_dvga_gain(MaxDvgaGain value); void set_carrier_sense_abs_thr(int8_t value); void set_carrier_sense_rel_thr(CarrierSenseRelThr value); void set_lna_priority(bool value); void set_filter_length_fsk_msk(FilterLengthFskMsk value); void set_filter_length_ask_ook(FilterLengthAskOok value); void set_freeze(Freeze value); void set_wait_time(WaitTime value); void set_hyst_level(HystLevel value); // Packet mode settings void set_packet_mode(bool value); void set_packet_length(uint8_t value); void set_crc_enable(bool value); void set_whitening(bool value); // Packet mode operations CC1101Error transmit_packet(const std::vector &packet); void register_listener(CC1101Listener *listener) { this->listeners_.push_back(listener); } Trigger, float, float, uint8_t> *get_packet_trigger() { return &this->packet_trigger_; } protected: uint16_t chip_id_{0}; bool initialized_{false}; float output_power_requested_{10.0f}; float output_power_effective_{10.0f}; uint8_t pa_table_[PA_TABLE_SIZE]{}; CC1101State state_; // GDO pin for packet reception InternalGPIOPin *gdo0_pin_{nullptr}; static void IRAM_ATTR gpio_intr(CC1101Component *arg); // Packet handling void call_listeners_(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi); Trigger, float, float, uint8_t> packet_trigger_; std::vector packet_; std::vector listeners_; // Low-level Helpers uint8_t strobe_(Command cmd); void write_(Register reg); void write_(Register reg, uint8_t value); void write_(Register reg, const uint8_t *buffer, size_t length); void read_(Register reg); void read_(Register reg, uint8_t *buffer, size_t length); // State Management bool wait_for_state_(State target_state, uint32_t timeout_ms = 100); bool enter_calibrated_(State target_state, Command cmd); void enter_idle_(); bool enter_rx_(); bool enter_tx_(); }; // Action Wrappers template class BeginTxAction : public Action, public Parented { public: void play(const Ts &...x) override { this->parent_->begin_tx(); } }; template class BeginRxAction : public Action, public Parented { public: void play(const Ts &...x) override { this->parent_->begin_rx(); } }; template class ResetAction : public Action, public Parented { public: void play(const Ts &...x) override { this->parent_->reset(); } }; template class SetIdleAction : public Action, public Parented { public: void play(const Ts &...x) override { this->parent_->set_idle(); } }; template class SendPacketAction : public Action, public Parented { public: void set_data_template(std::function(Ts...)> func) { this->data_func_ = func; } void set_data_static(const uint8_t *data, size_t len) { this->data_static_ = data; this->data_static_len_ = len; } void play(const Ts &...x) override { if (this->data_func_) { auto data = this->data_func_(x...); this->parent_->transmit_packet(data); } else if (this->data_static_ != nullptr) { std::vector data(this->data_static_, this->data_static_ + this->data_static_len_); this->parent_->transmit_packet(data); } } protected: std::function(Ts...)> data_func_{}; const uint8_t *data_static_{nullptr}; size_t data_static_len_{0}; }; template class SetSymbolRateAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, symbol_rate) void play(const Ts &...x) override { this->parent_->set_symbol_rate(this->symbol_rate_.value(x...)); } }; template class SetFrequencyAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, frequency) void play(const Ts &...x) override { this->parent_->set_frequency(this->frequency_.value(x...)); } }; template class SetOutputPowerAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, output_power) void play(const Ts &...x) override { this->parent_->set_output_power(this->output_power_.value(x...)); } }; template class SetModulationTypeAction : public Action, public Parented { public: TEMPLATABLE_VALUE(Modulation, modulation_type) void play(const Ts &...x) override { this->parent_->set_modulation_type(this->modulation_type_.value(x...)); } }; template class SetRxAttenuationAction : public Action, public Parented { public: TEMPLATABLE_VALUE(RxAttenuation, rx_attenuation) void play(const Ts &...x) override { this->parent_->set_rx_attenuation(this->rx_attenuation_.value(x...)); } }; template class SetDcBlockingFilterAction : public Action, public Parented { public: TEMPLATABLE_VALUE(bool, dc_blocking_filter) void play(const Ts &...x) override { this->parent_->set_dc_blocking_filter(this->dc_blocking_filter_.value(x...)); } }; template class SetManchesterAction : public Action, public Parented { public: TEMPLATABLE_VALUE(bool, manchester) void play(const Ts &...x) override { this->parent_->set_manchester(this->manchester_.value(x...)); } }; template class SetFilterBandwidthAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, filter_bandwidth) void play(const Ts &...x) override { this->parent_->set_filter_bandwidth(this->filter_bandwidth_.value(x...)); } }; template class SetFskDeviationAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, fsk_deviation) void play(const Ts &...x) override { this->parent_->set_fsk_deviation(this->fsk_deviation_.value(x...)); } }; template class SetMskDeviationAction : public Action, public Parented { public: TEMPLATABLE_VALUE(uint8_t, msk_deviation) void play(const Ts &...x) override { this->parent_->set_msk_deviation(this->msk_deviation_.value(x...)); } }; template class SetChannelAction : public Action, public Parented { public: TEMPLATABLE_VALUE(uint8_t, channel) void play(const Ts &...x) override { this->parent_->set_channel(this->channel_.value(x...)); } }; template class SetChannelSpacingAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, channel_spacing) void play(const Ts &...x) override { this->parent_->set_channel_spacing(this->channel_spacing_.value(x...)); } }; template class SetIfFrequencyAction : public Action, public Parented { public: TEMPLATABLE_VALUE(float, if_frequency) void play(const Ts &...x) override { this->parent_->set_if_frequency(this->if_frequency_.value(x...)); } }; } // namespace esphome::cc1101