diff --git a/esphome/components/rp2040_pwm/rp2040_pwm.cpp b/esphome/components/rp2040_pwm/rp2040_pwm.cpp index bf2a446edf..3f95125578 100644 --- a/esphome/components/rp2040_pwm/rp2040_pwm.cpp +++ b/esphome/components/rp2040_pwm/rp2040_pwm.cpp @@ -6,7 +6,9 @@ #include "esphome/core/log.h" #include "esphome/core/macros.h" -#include +#include +#include +#include namespace esphome { namespace rp2040_pwm { @@ -15,10 +17,17 @@ static const char *const TAG = "rp2040_pwm"; void RP2040PWM::setup() { ESP_LOGCONFIG(TAG, "Setting up RP2040 PWM Output..."); - this->pin_->setup(); - this->pwm_ = new mbed::PwmOut((PinName) this->pin_->get_pin()); - this->turn_off(); + + this->setup_pwm_(); } + +void RP2040PWM::setup_pwm_() { + pwm_config config = pwm_get_default_config(); + pwm_config_set_clkdiv(&config, clock_get_hz(clk_sys) / (255.0f * this->frequency_)); + pwm_config_set_wrap(&config, 254); + pwm_init(pwm_gpio_to_slice_num(this->pin_->get_pin()), &config, true); +} + void RP2040PWM::dump_config() { ESP_LOGCONFIG(TAG, "RP2040 PWM:"); LOG_PIN(" Pin: ", this->pin_); @@ -33,10 +42,13 @@ void HOT RP2040PWM::write_state(float state) { state = 1.0f - state; } - auto total_time_us = static_cast(roundf(1e6f / this->frequency_)); + if (frequency_changed_) { + this->setup_pwm_(); + frequency_changed_ = false; + } - this->pwm_->period_us(total_time_us); - this->pwm_->write(state); + gpio_set_function(this->pin_->get_pin(), GPIO_FUNC_PWM); + pwm_set_gpio_level(this->pin_->get_pin(), state * 255.0f); } } // namespace rp2040_pwm diff --git a/esphome/components/rp2040_pwm/rp2040_pwm.h b/esphome/components/rp2040_pwm/rp2040_pwm.h index e348f131c2..903079df17 100644 --- a/esphome/components/rp2040_pwm/rp2040_pwm.h +++ b/esphome/components/rp2040_pwm/rp2040_pwm.h @@ -7,11 +7,11 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" -#include "drivers/PwmOut.h" - namespace esphome { namespace rp2040_pwm { +static bool frequency_changed_ = false; + class RP2040PWM : public output::FloatOutput, public Component { public: void set_pin(InternalGPIOPin *pin) { pin_ = pin; } @@ -19,6 +19,7 @@ class RP2040PWM : public output::FloatOutput, public Component { /// Dynamically update frequency void update_frequency(float frequency) override { this->set_frequency(frequency); + frequency_changed_ = true; this->write_state(this->last_output_); } @@ -31,8 +32,9 @@ class RP2040PWM : public output::FloatOutput, public Component { protected: void write_state(float state) override; + void setup_pwm_(); + InternalGPIOPin *pin_; - mbed::PwmOut *pwm_; float frequency_{1000.0}; /// Cache last output level for dynamic frequency updating float last_output_{0.0};