7 #include <esp32-hal-ledc.h> 9 #include <driver/ledc.h> 13 #define CLOCK_FREQUENCY 80e6f 16 #ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK 17 #undef CLOCK_FREQUENCY 19 #define CLOCK_FREQUENCY 40e6f 22 #ifdef SOC_LEDC_SUPPORT_APB_CLOCK 23 #define DEFAULT_CLK LEDC_USE_APB_CLK 25 #define DEFAULT_CLK LEDC_AUTO_CLK 29 static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
34 static const char *
const TAG =
"ledc.output";
36 static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
38 #if SOC_LEDC_SUPPORT_HS_MODE 40 inline ledc_mode_t
get_speed_mode(uint8_t channel) {
return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
45 inline ledc_mode_t
get_speed_mode(uint8_t) {
return LEDC_LOW_SPEED_MODE; }
52 const float max_div_num = ((1 << MAX_RES_BITS) - 1) / (low_frequency ? 32.0f : 256.0f);
53 return CLOCK_FREQUENCY / (max_div_num * float(1 << bit_depth));
57 ESP_LOGV(TAG,
"Calculating resolution bit-depth for frequency %f", frequency);
58 for (
int i = MAX_RES_BITS; i >= 1; i--) {
61 if (min_frequency <= frequency && frequency <= max_frequency) {
62 ESP_LOGV(TAG,
"Resolution calculated as %d", i);
71 uint8_t channel, uint8_t &bit_depth,
float frequency) {
74 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", frequency);
77 ledc_timer_config_t timer_conf{};
78 timer_conf.speed_mode = speed_mode;
79 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(bit_depth);
80 timer_conf.timer_num = timer_num;
81 timer_conf.freq_hz = (uint32_t) frequency;
82 timer_conf.clk_cfg = DEFAULT_CLK;
85 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
86 esp_err_t init_result = ESP_FAIL;
87 while (attempt_count_max > 0 && init_result != ESP_OK) {
88 init_result = ledc_timer_config(&timer_conf);
89 if (init_result != ESP_OK) {
90 ESP_LOGW(TAG,
"Unable to initialize timer with frequency %.1f and bit depth of %u", frequency, bit_depth);
92 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(--bit_depth);
103 return static_cast<int>(angle * ((1U << bit_depth) - 1) / 360.);
105 #endif // USE_ESP_IDF 109 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
114 state = 1.0f - state;
117 const uint32_t max_duty = (uint32_t(1) << this->
bit_depth_) - 1;
118 const float duty_rounded = roundf(state * max_duty);
119 auto duty =
static_cast<uint32_t
>(duty_rounded);
120 ESP_LOGV(TAG,
"Setting duty: %" PRIu32
" on channel %u", duty, this->
channel_);
126 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
128 if (duty == max_duty) {
129 ledc_stop(speed_mode, chan_num, 1);
130 }
else if (duty == 0) {
131 ledc_stop(speed_mode, chan_num, 0);
133 ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint);
134 ledc_update_duty(speed_mode, chan_num);
140 ESP_LOGV(TAG,
"Entering setup...");
149 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
150 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
152 esp_err_t timer_init_result =
155 if (timer_init_result != ESP_OK) {
156 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
162 ESP_LOGV(TAG,
"Configured frequency %f with a bit depth of %u bits", this->
frequency_, this->
bit_depth_);
163 ESP_LOGV(TAG,
"Angle of %.1f° results in hpoint %u", this->
phase_angle_, hpoint);
165 ledc_channel_config_t chan_conf{};
167 chan_conf.speed_mode = speed_mode;
168 chan_conf.channel = chan_num;
169 chan_conf.intr_type = LEDC_INTR_DISABLE;
170 chan_conf.timer_sel = timer_num;
172 chan_conf.hpoint = hpoint;
173 ledc_channel_config(&chan_conf);
180 ESP_LOGCONFIG(TAG,
"LEDC Output:");
181 LOG_PIN(
" Pin ", this->
pin_);
182 ESP_LOGCONFIG(TAG,
" LEDC Channel: %u", this->
channel_);
183 ESP_LOGCONFIG(TAG,
" PWM Frequency: %.1f Hz", this->
frequency_);
184 ESP_LOGCONFIG(TAG,
" Phase angle: %.1f°", this->
phase_angle_);
185 ESP_LOGCONFIG(TAG,
" Bit depth: %u", this->
bit_depth_);
187 ESP_LOGV(TAG,
" Min frequency for bit depth: %f",
190 ESP_LOGV(TAG,
" Min frequency for bit depth-1: %f",
193 ESP_LOGV(TAG,
" Min frequency for bit depth+1: %f",
195 ESP_LOGV(TAG,
" Max res bits: %d", MAX_RES_BITS);
196 ESP_LOGV(TAG,
" Clock frequency: %f", CLOCK_FREQUENCY);
201 if (!bit_depth_opt.has_value()) {
202 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", this->
frequency_);
208 ESP_LOGV(TAG,
"Using Arduino API - Trying to define channel, frequency and bit depth...");
209 u_int32_t configured_frequency = 0;
212 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
213 while (attempt_count_max > 0 && configured_frequency == 0) {
214 ESP_LOGV(TAG,
"Trying initialize channel %u with frequency %.1f and bit depth of %u...", this->
channel_,
217 if (configured_frequency != 0) {
220 ESP_LOGV(TAG,
"Configured frequency: %u with bit depth: %u", configured_frequency, this->
bit_depth_);
222 ESP_LOGW(TAG,
"Unable to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
230 if (configured_frequency == 0) {
231 ESP_LOGE(TAG,
"Permanently failed to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
237 #endif // USE_ARDUINO 240 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
245 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
246 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
248 esp_err_t timer_init_result =
251 if (timer_init_result != ESP_OK) {
252 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
void status_set_error(const char *message="unspecified")
ledc_mode_t get_speed_mode(uint8_t channel)
void write_state(float state) override
Override FloatOutput's write_state.
void status_clear_error()
constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth)
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