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 #ifdef SOC_LEDC_SUPPORT_APB_CLOCK 21 #define DEFAULT_CLK LEDC_USE_APB_CLK 23 #define DEFAULT_CLK LEDC_AUTO_CLK 27 static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
32 static const char *
const TAG =
"ledc.output";
34 static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
36 #if SOC_LEDC_SUPPORT_HS_MODE 38 inline ledc_mode_t
get_speed_mode(uint8_t channel) {
return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
43 inline ledc_mode_t
get_speed_mode(uint8_t) {
return LEDC_LOW_SPEED_MODE; }
50 const float max_div_num = ((1 << MAX_RES_BITS) - 1) / (low_frequency ? 32.0f : 256.0f);
51 return CLOCK_FREQUENCY / (max_div_num * float(1 << bit_depth));
55 ESP_LOGD(TAG,
"Calculating resolution bit-depth for frequency %f", frequency);
56 for (
int i = MAX_RES_BITS; i >= 1; i--) {
59 if (min_frequency <= frequency && frequency <= max_frequency) {
60 ESP_LOGD(TAG,
"Resolution calculated as %d", i);
69 uint8_t channel, uint8_t &bit_depth,
float frequency) {
72 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", frequency);
75 ledc_timer_config_t timer_conf{};
76 timer_conf.speed_mode = speed_mode;
77 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(bit_depth);
78 timer_conf.timer_num = timer_num;
79 timer_conf.freq_hz = (uint32_t) frequency;
80 timer_conf.clk_cfg = DEFAULT_CLK;
83 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
84 esp_err_t init_result = ESP_FAIL;
85 while (attempt_count_max > 0 && init_result != ESP_OK) {
86 init_result = ledc_timer_config(&timer_conf);
87 if (init_result != ESP_OK) {
88 ESP_LOGW(TAG,
"Unable to initialize timer with frequency %.1f and bit depth of %u", frequency, bit_depth);
90 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(--bit_depth);
101 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
106 state = 1.0f - state;
109 const uint32_t max_duty = (uint32_t(1) << this->
bit_depth_) - 1;
110 const float duty_rounded = roundf(state * max_duty);
111 auto duty =
static_cast<uint32_t
>(duty_rounded);
114 ESP_LOGV(TAG,
"Setting duty: %u on channel %u", duty, this->
channel_);
119 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
120 ledc_set_duty(speed_mode, chan_num, duty);
121 ledc_update_duty(speed_mode, chan_num);
126 ESP_LOGV(TAG,
"Entering setup...");
135 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
136 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
138 esp_err_t timer_init_result =
141 if (timer_init_result != ESP_OK) {
142 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
147 ESP_LOGV(TAG,
"Configured frequency %f with a bit depth of %u bits", this->
frequency_, this->
bit_depth_);
149 ledc_channel_config_t chan_conf{};
151 chan_conf.speed_mode = speed_mode;
152 chan_conf.channel = chan_num;
153 chan_conf.intr_type = LEDC_INTR_DISABLE;
154 chan_conf.timer_sel = timer_num;
156 chan_conf.hpoint = 0;
157 ledc_channel_config(&chan_conf);
164 ESP_LOGCONFIG(TAG,
"LEDC Output:");
165 LOG_PIN(
" Pin ", this->
pin_);
166 ESP_LOGCONFIG(TAG,
" LEDC Channel: %u", this->
channel_);
167 ESP_LOGCONFIG(TAG,
" PWM Frequency: %.1f Hz", this->
frequency_);
168 ESP_LOGCONFIG(TAG,
" Bit depth: %u", this->
bit_depth_);
170 ESP_LOGV(TAG,
" Min frequency for bit depth: %f",
173 ESP_LOGV(TAG,
" Min frequency for bit depth-1: %f",
176 ESP_LOGV(TAG,
" Min frequency for bit depth+1: %f",
178 ESP_LOGV(TAG,
" Max res bits: %d", MAX_RES_BITS);
179 ESP_LOGV(TAG,
" Clock frequency: %f", CLOCK_FREQUENCY);
184 if (!bit_depth_opt.has_value()) {
185 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", this->
frequency_);
191 ESP_LOGV(TAG,
"Using Arduino API - Trying to define channel, frequency and bit depth...");
192 u_int32_t configured_frequency = 0;
195 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
196 while (attempt_count_max > 0 && configured_frequency == 0) {
197 ESP_LOGV(TAG,
"Trying initialize channel %u with frequency %.1f and bit depth of %u...", this->
channel_,
200 if (configured_frequency != 0) {
203 ESP_LOGV(TAG,
"Configured frequency: %u with bit depth: %u", configured_frequency, this->
bit_depth_);
205 ESP_LOGW(TAG,
"Unable to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
213 if (configured_frequency == 0) {
214 ESP_LOGE(TAG,
"Permanently failed to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
220 #endif // USE_ARDUINO 223 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
228 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
229 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
231 esp_err_t timer_init_result =
234 if (timer_init_result != ESP_OK) {
235 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)
Implementation of SPI Controller mode.
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