7 #include <esp32-hal-ledc.h> 9 #include <driver/ledc.h> 11 #define CLOCK_FREQUENCY 80e6f 14 #ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK 15 #undef CLOCK_FREQUENCY 17 #define CLOCK_FREQUENCY 40e6f 20 #define DEFAULT_CLK LEDC_USE_APB_CLK 23 static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
28 static const char *
const TAG =
"ledc.output";
30 static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
32 #if SOC_LEDC_SUPPORT_HS_MODE 34 inline ledc_mode_t
get_speed_mode(uint8_t channel) {
return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
39 inline ledc_mode_t
get_speed_mode(uint8_t) {
return LEDC_LOW_SPEED_MODE; }
46 const float max_div_num = ((1 << MAX_RES_BITS) - 1) / (low_frequency ? 32.0f : 256.0f);
47 return CLOCK_FREQUENCY / (max_div_num * float(1 << bit_depth));
51 ESP_LOGD(TAG,
"Calculating resolution bit-depth for frequency %f", frequency);
52 for (
int i = MAX_RES_BITS; i >= 1; i--) {
55 if (min_frequency <= frequency && frequency <= max_frequency) {
56 ESP_LOGD(TAG,
"Resolution calculated as %d", i);
65 uint8_t channel, uint8_t &bit_depth,
float frequency) {
68 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", frequency);
71 ledc_timer_config_t timer_conf{};
72 timer_conf.speed_mode = speed_mode;
73 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(bit_depth);
74 timer_conf.timer_num = timer_num;
75 timer_conf.freq_hz = (uint32_t) frequency;
76 timer_conf.clk_cfg = DEFAULT_CLK;
79 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
80 esp_err_t init_result = ESP_FAIL;
81 while (attempt_count_max > 0 && init_result != ESP_OK) {
82 init_result = ledc_timer_config(&timer_conf);
83 if (init_result != ESP_OK) {
84 ESP_LOGW(TAG,
"Unable to initialize timer with frequency %.1f and bit depth of %u", frequency, bit_depth);
86 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(--bit_depth);
97 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
102 state = 1.0f - state;
105 const uint32_t max_duty = (uint32_t(1) << this->
bit_depth_) - 1;
106 const float duty_rounded = roundf(state * max_duty);
107 auto duty =
static_cast<uint32_t
>(duty_rounded);
110 ESP_LOGV(TAG,
"Setting duty: %u on channel %u", duty, this->
channel_);
115 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
116 ledc_set_duty(speed_mode, chan_num, duty);
117 ledc_update_duty(speed_mode, chan_num);
122 ESP_LOGV(TAG,
"Entering setup...");
131 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
132 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
134 esp_err_t timer_init_result =
137 if (timer_init_result != ESP_OK) {
138 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
143 ESP_LOGV(TAG,
"Configured frequency %f with a bit depth of %u bits", this->
frequency_, this->
bit_depth_);
145 ledc_channel_config_t chan_conf{};
147 chan_conf.speed_mode = speed_mode;
148 chan_conf.channel = chan_num;
149 chan_conf.intr_type = LEDC_INTR_DISABLE;
150 chan_conf.timer_sel = timer_num;
152 chan_conf.hpoint = 0;
153 ledc_channel_config(&chan_conf);
160 ESP_LOGCONFIG(TAG,
"LEDC Output:");
161 LOG_PIN(
" Pin ", this->
pin_);
162 ESP_LOGCONFIG(TAG,
" LEDC Channel: %u", this->
channel_);
163 ESP_LOGCONFIG(TAG,
" PWM Frequency: %.1f Hz", this->
frequency_);
164 ESP_LOGCONFIG(TAG,
" Bit depth: %u", this->
bit_depth_);
166 ESP_LOGV(TAG,
" Min frequency for bit depth: %f",
169 ESP_LOGV(TAG,
" Min frequency for bit depth-1: %f",
172 ESP_LOGV(TAG,
" Min frequency for bit depth+1: %f",
174 ESP_LOGV(TAG,
" Max res bits: %d", MAX_RES_BITS);
175 ESP_LOGV(TAG,
" Clock frequency: %f", CLOCK_FREQUENCY);
180 if (!bit_depth_opt.has_value()) {
181 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", this->
frequency_);
187 ESP_LOGV(TAG,
"Using Arduino API - Trying to define channel, frequency and bit depth...");
188 u_int32_t configured_frequency = 0;
191 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
192 while (attempt_count_max > 0 && configured_frequency == 0) {
193 ESP_LOGV(TAG,
"Trying initialize channel %u with frequency %.1f and bit depth of %u...", this->
channel_,
196 if (configured_frequency != 0) {
199 ESP_LOGV(TAG,
"Configured frequency: %u with bit depth: %u", configured_frequency, this->
bit_depth_);
201 ESP_LOGW(TAG,
"Unable to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
209 if (configured_frequency == 0) {
210 ESP_LOGE(TAG,
"Permanently failed to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
216 #endif // USE_ARDUINO 219 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
224 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
225 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
227 esp_err_t timer_init_result =
230 if (timer_init_result != ESP_OK) {
231 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
virtual void turn_off()
Disable this binary output.
uint8_t next_ledc_channel
void update_frequency(float frequency) override
Dynamically change frequency at runtime.
virtual uint8_t get_pin() const =0
ledc_mode_t get_speed_mode(uint8_t channel)
void write_state(float state) override
Override FloatOutput's write_state.
void status_clear_error()
void setup() override
Setup LEDC.
void dump_config() override
float ledc_min_frequency_for_bit_depth(uint8_t bit_depth, bool low_frequency)
optional< uint8_t > ledc_bit_depth_for_frequency(float frequency)
esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num, uint8_t channel, uint8_t &bit_depth, float frequency)
float ledc_max_frequency_for_bit_depth(uint8_t bit_depth)
virtual bool is_inverted() const =0