26#include <idfxx/intr_alloc>
30#include <frequency/frequency>
53#if SOC_LEDC_SUPPORT_HS_MODE
72#if SOC_LEDC_CHANNEL_NUM > 6
75#if SOC_LEDC_CHANNEL_NUM > 7
89#if SOC_LEDC_SUPPORT_APB_CLOCK
92#if SOC_LEDC_SUPPORT_REF_TICK
95#if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
98#if SOC_LEDC_SUPPORT_XTAL_CLOCK
140template<
int N, speed_mode M>
141struct timer_constant;
170 template<
int N, speed_mode M>
198#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
315#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
341#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
358 template<
typename Rep,
typename Period>
377 template<
typename Rep,
typename Period>
379 auto ns = std::chrono::ceil<std::chrono::nanoseconds>(
period).count();
386#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
403#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
420#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
442 , _speed_mode(mode) {}
449template<
int N, speed_mode M>
450struct timer_constant {
452 static constexpr timer value{
N,
M};
462inline constexpr timer timer_0 = timer_constant<0, speed_mode::low_speed>::value;
463inline constexpr timer timer_1 = timer_constant<1, speed_mode::low_speed>::value;
464inline constexpr timer timer_2 = timer_constant<2, speed_mode::low_speed>::value;
465inline constexpr timer timer_3 = timer_constant<3, speed_mode::low_speed>::value;
467#if SOC_LEDC_SUPPORT_HS_MODE
468inline constexpr timer hs_timer_0 = timer_constant<0, speed_mode::high_speed>::value;
469inline constexpr timer hs_timer_1 = timer_constant<1, speed_mode::high_speed>::value;
470inline constexpr timer hs_timer_2 = timer_constant<2, speed_mode::high_speed>::value;
471inline constexpr timer hs_timer_3 = timer_constant<3, speed_mode::high_speed>::value;
490#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
760#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
786#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
839#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
854 template<
typename Rep,
typename Period>
870 template<
typename Rep,
typename Period>
872 return _try_set_pulse_width(std::chrono::ceil<std::chrono::nanoseconds>(
width));
875#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
889 template<
typename Rep,
typename Period>
892 const std::chrono::duration<Rep, Period>& duration,
914 template<
typename Rep,
typename Period>
917 const std::chrono::duration<Rep, Period>& duration,
920 return _try_fade_to_duty(
922 std::chrono::ceil<std::chrono::milliseconds>(duration),
927#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
941 template<
typename Rep,
typename Period>
944 const std::chrono::duration<Rep, Period>& duration,
966 template<
typename Rep,
typename Period>
969 const std::chrono::duration<Rep, Period>& duration,
972 return _try_fade_to_duty(
target_duty, std::chrono::ceil<std::chrono::milliseconds>(duration), mode);
975#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
991 template<
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
993 const std::chrono::duration<Rep1, Period1>&
target_width,
994 const std::chrono::duration<Rep2, Period2>& duration,
1018 template<
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
1020 const std::chrono::duration<Rep1, Period1>&
target_width,
1021 const std::chrono::duration<Rep2, Period2>& duration,
1024 return _try_fade_to_pulse_width(
1025 std::chrono::ceil<std::chrono::nanoseconds>(
target_width),
1026 std::chrono::ceil<std::chrono::milliseconds>(duration),
1031#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1071#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
1072#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1109#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1133#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1189#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1221#if SOC_LEDC_SUPPORT_FADE_STOP
1222#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1244#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1284#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1344#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1375[[nodiscard]]
inline std::string to_string(
const pwm::timer& t) {
1377#if SOC_LEDC_SUPPORT_HS_MODE
1378 if (t.speed_mode() == pwm::speed_mode::high_speed) {
1379 s =
"PWM_HS_TIMER_";
1386 s += std::to_string(t.num());
1397[[nodiscard]]
inline std::string
to_string(pwm::channel ch) {
1398 return "PWM_CH_" + std::to_string(std::to_underlying(ch));
1408[[nodiscard]]
inline std::string
to_string(pwm::speed_mode m) {
1410 case pwm::speed_mode::low_speed:
1412#if SOC_LEDC_SUPPORT_HS_MODE
1413 case pwm::speed_mode::high_speed:
1414 return "high_speed";
1417 return "unknown(" + std::to_string(std::to_underlying(m)) +
")";
1423#include "sdkconfig.h"
1424#ifdef CONFIG_IDFXX_STD_FORMAT
1429struct formatter<
idfxx::pwm::timer> {
1430 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1432 template<
typename FormatContext>
1435 return std::copy(s.begin(), s.end(), ctx.out());
1439struct formatter<
idfxx::pwm::channel> {
1440 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1442 template<
typename FormatContext>
1445 return std::copy(s.begin(), s.end(), ctx.out());
1449struct formatter<
idfxx::pwm::speed_mode> {
1450 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1452 template<
typename FormatContext>
1455 return std::copy(s.begin(), s.end(), ctx.out());
level
GPIO output/input level.
An active PWM output binding a timer, channel, and GPIO pin.
result< void > try_fade_to(float target, const std::chrono::duration< Rep, Period > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target duty ratio over the specified duration.
bool is_active() const noexcept
Returns true if the output is still actively driving the channel.
enum channel release() noexcept
Releases ownership of the channel without stopping the PWM output.
static result< void > try_install_fade_service(idfxx::intr_levels levels=intr_level_lowmed, idfxx::flags< intr_flag > flags={})
Installs the PWM fade service.
result< void > try_fade_to_duty_ticks(uint32_t target_duty, const std::chrono::duration< Rep, Period > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target duty in ticks over the specified duration.
void fade_to_duty_ticks(uint32_t target_duty, const std::chrono::duration< Rep, Period > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target duty in ticks over the specified duration.
result< void > try_set_pulse_width(const std::chrono::duration< Rep, Period > &width)
Sets the PWM duty cycle as a pulse width duration.
result< void > try_set_duty_ticks(uint32_t duty)
Sets the PWM duty cycle in ticks.
void set_duty_ticks(uint32_t duty)
Sets the PWM duty cycle in ticks.
void fade_with_step(uint32_t target_duty, uint32_t scale, uint32_t cycle_num, enum fade_mode mode=fade_mode::no_wait)
Starts a fade to a target duty in ticks with step control.
uint32_t ticks_max() const noexcept
Returns the maximum duty ticks for the configured resolution.
result< void > try_stop(idfxx::gpio::level idle_level=idfxx::gpio::level::low)
Stops PWM output and sets the GPIO to an idle level.
result< void > try_set_duty(float duty)
Sets the PWM duty cycle as a ratio.
output(output &&other) noexcept
float duty() const
Returns the current duty cycle as a ratio.
void register_fade_end_callback(std::move_only_function< bool() const > callback)
Registers a callback for fade-end events.
output & operator=(output &&other) noexcept
~output()
Destroys the output, stopping PWM on the bound GPIO.
output(const output &)=delete
result< void > try_fade_with_step(uint32_t target_duty, uint32_t scale, uint32_t cycle_num, enum fade_mode mode=fade_mode::no_wait)
Starts a fade to the target duty with step control.
void stop(idfxx::gpio::level idle_level=idfxx::gpio::level::low)
Stops PWM output and sets the GPIO to an idle level.
result< void > try_fade_to_pulse_width(const std::chrono::duration< Rep1, Period1 > &target_width, const std::chrono::duration< Rep2, Period2 > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target pulse width over the specified duration.
static void install_fade_service(idfxx::intr_levels levels=intr_level_lowmed, idfxx::flags< intr_flag > flags={})
Installs the PWM fade service.
void fade_to_pulse_width(const std::chrono::duration< Rep1, Period1 > &target_width, const std::chrono::duration< Rep2, Period2 > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target pulse width over the specified duration.
result< void > try_register_fade_end_callback(std::move_only_function< bool() const > callback)
Registers a callback for fade-end events.
std::chrono::nanoseconds pulse_width() const
Returns the current pulse width as a duration.
result< void > try_set_duty_ticks(uint32_t duty, uint32_t hpoint)
Sets the PWM duty cycle in ticks with high point.
enum channel channel() const noexcept
Returns the channel slot that was bound to this output.
static void uninstall_fade_service()
Uninstalls the PWM fade service.
output & operator=(const output &)=delete
void set_pulse_width(const std::chrono::duration< Rep, Period > &width)
Sets the PWM duty cycle as a pulse width duration.
friend result< output > try_start(idfxx::gpio gpio, const class timer &tmr, enum channel ch, const output_config &cfg)
void set_duty(float duty)
Sets the PWM duty cycle as a ratio.
void set_duty_ticks(uint32_t duty, uint32_t hpoint)
Sets the PWM duty cycle in ticks with high point.
uint32_t duty_ticks() const
Returns the current duty cycle in ticks.
void fade_to(float target, const std::chrono::duration< Rep, Period > &duration, enum fade_mode mode=fade_mode::no_wait)
Fades to a target duty ratio over the specified duration.
A lightweight identifier for a hardware PWM timer.
void configure(const struct config &cfg)
Configures the timer with the given parameters.
result< void > try_configure(const struct config &cfg)
Configures the timer with the given parameters.
uint32_t ticks_max() const noexcept
Returns the maximum duty ticks for the configured resolution.
uint8_t resolution_bits() const noexcept
Returns the configured resolution in bits.
timer & operator=(timer &&)=default
friend result< output > try_start(idfxx::gpio, const config &, const output_config &)
Starts PWM output with automatic allocation and custom output configuration.
constexpr unsigned int num() const noexcept
Returns the timer number (0-3).
freq::hertz frequency() const
Returns the current timer frequency.
result< void > try_set_frequency(freq::hertz frequency)
Changes the timer frequency.
friend struct timer_constant
result< void > try_configure(freq::hertz frequency, uint8_t resolution_bits=13)
Configures the timer with frequency and resolution.
constexpr enum speed_mode speed_mode() const noexcept
Returns the speed mode.
void resume()
Resumes the timer counter.
timer(const timer &)=default
std::chrono::nanoseconds tick_period() const
Returns the duration of a single timer tick.
timer & operator=(const timer &)=default
constexpr bool operator==(const timer &other) const =default
std::chrono::nanoseconds period() const
Returns the PWM period (1 / frequency) as a duration.
void set_period(const std::chrono::duration< Rep, Period > &period)
Changes the timer period.
result< void > try_pause()
Pauses the timer counter.
result< void > try_resume()
Resumes the timer counter.
void pause()
Pauses the timer counter.
void reset()
Resets the timer counter.
void configure(freq::hertz frequency, uint8_t resolution_bits=13)
Configures the timer with frequency and resolution.
result< void > try_reset()
Resets the timer counter.
void set_frequency(freq::hertz frequency)
Changes the timer frequency.
result< void > try_set_period(const std::chrono::duration< Rep, Period > &period)
Changes the timer period.
bool is_configured() const noexcept
Returns true if the timer has been configured.
friend std::optional< timer > get_timer(enum channel, enum speed_mode)
Returns the timer associated with an active channel, if any.
High-resolution timer with microsecond precision.
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
result< output > try_start(idfxx::gpio gpio, const timer &tmr, enum channel ch)
Starts PWM output on a GPIO pin.
sleep_mode
Channel behavior during light sleep.
bool is_active(enum channel ch, enum speed_mode mode=speed_mode::low_speed)
Returns true if the specified channel currently has an active output.
speed_mode
PWM speed mode selection.
void stop(enum channel ch, enum speed_mode mode=speed_mode::low_speed, idfxx::gpio::level idle_level=idfxx::gpio::level::low)
Stops PWM output on a channel and sets it to an idle level.
channel
PWM channel slot identifiers.
output start(idfxx::gpio gpio, const timer &tmr, enum channel ch)
Starts PWM output on a GPIO pin.
fade_mode
Fade operation blocking mode.
result< void > try_stop(enum channel ch, enum speed_mode mode=speed_mode::low_speed, idfxx::gpio::level idle_level=idfxx::gpio::level::low)
Stops PWM output on a channel and sets it to an idle level.
std::optional< timer > get_timer(enum channel ch, enum speed_mode mode=speed_mode::low_speed)
Returns the timer associated with an active channel, if any.
clk_source
PWM timer clock source.
@ no_alive_no_pd
No output, keep power domain on (default)
@ keep_alive
Maintain PWM output during light sleep.
@ no_alive_allow_pd
No output, allow power domain off (saves power)
@ low_speed
Low-speed mode (available on all targets)
@ no_wait
Return immediately, fade runs in background.
@ wait_done
Block until the fade completes.
@ auto_select
Automatic clock source selection.
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
@ invalid_arg
Invalid argument.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
constexpr intr_levels intr_level_lowmed
Low and medium priority levels (1-3). These can be handled in C / C++.
Parameters for a single step in a multi-step hardware fade.
bool increasing
Duty change direction: true = increase, false = decrease.
uint32_t scale
Duty change per step.
uint32_t cycle_num
Number of PWM cycles per step.
uint32_t step_num
Total number of steps.
Output configuration parameters.
bool output_invert
Invert the output signal.
float duty
Initial duty cycle ratio (0.0 to 1.0).
int hpoint
High point in the PWM cycle.
Timer configuration parameters.
uint8_t resolution_bits
Duty resolution in bits (1 to SOC_LEDC_TIMER_BIT_WIDTH).
freq::hertz frequency
PWM frequency.