26#include <idfxx/intr_alloc>
30#include <frequency/frequency>
50#if SOC_LEDC_SUPPORT_HS_MODE
69#if SOC_LEDC_CHANNEL_NUM > 6
72#if SOC_LEDC_CHANNEL_NUM > 7
86#if SOC_LEDC_SUPPORT_APB_CLOCK
89#if SOC_LEDC_SUPPORT_REF_TICK
92#if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
95#if SOC_LEDC_SUPPORT_XTAL_CLOCK
126template<
int N, speed_mode M>
127struct timer_constant;
156 template<
int N, speed_mode M>
186#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
303#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
329#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
346 template<
typename Rep,
typename Period>
365 template<
typename Rep,
typename Period>
367 auto ns = std::chrono::ceil<std::chrono::nanoseconds>(
period).count();
374#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
391#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
408#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
430 , _speed_mode(mode) {}
437template<
int N, speed_mode M>
438struct timer_constant {
440 static constexpr timer value{
N,
M};
450inline constexpr timer timer_0 = timer_constant<0, speed_mode::low_speed>::value;
451inline constexpr timer timer_1 = timer_constant<1, speed_mode::low_speed>::value;
452inline constexpr timer timer_2 = timer_constant<2, speed_mode::low_speed>::value;
453inline constexpr timer timer_3 = timer_constant<3, speed_mode::low_speed>::value;
455#if SOC_LEDC_SUPPORT_HS_MODE
456inline constexpr timer hs_timer_0 = timer_constant<0, speed_mode::high_speed>::value;
457inline constexpr timer hs_timer_1 = timer_constant<1, speed_mode::high_speed>::value;
458inline constexpr timer hs_timer_2 = timer_constant<2, speed_mode::high_speed>::value;
459inline constexpr timer hs_timer_3 = timer_constant<3, speed_mode::high_speed>::value;
478#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
737#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
763#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
816#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
831 template<
typename Rep,
typename Period>
847 template<
typename Rep,
typename Period>
849 return _try_set_pulse_width(std::chrono::ceil<std::chrono::nanoseconds>(
width));
852#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
866 template<
typename Rep,
typename Period>
869 const std::chrono::duration<Rep, Period>& duration,
891 template<
typename Rep,
typename Period>
894 const std::chrono::duration<Rep, Period>& duration,
897 return _try_fade_to_duty(
899 std::chrono::ceil<std::chrono::milliseconds>(duration),
904#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
918 template<
typename Rep,
typename Period>
921 const std::chrono::duration<Rep, Period>& duration,
943 template<
typename Rep,
typename Period>
946 const std::chrono::duration<Rep, Period>& duration,
949 return _try_fade_to_duty(
target_duty, std::chrono::ceil<std::chrono::milliseconds>(duration), mode);
952#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
968 template<
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
970 const std::chrono::duration<Rep1, Period1>&
target_width,
971 const std::chrono::duration<Rep2, Period2>& duration,
995 template<
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
997 const std::chrono::duration<Rep1, Period1>&
target_width,
998 const std::chrono::duration<Rep2, Period2>& duration,
1001 return _try_fade_to_pulse_width(
1002 std::chrono::ceil<std::chrono::nanoseconds>(
target_width),
1003 std::chrono::ceil<std::chrono::milliseconds>(duration),
1008#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1048#if SOC_LEDC_SUPPORT_FADE_STOP
1049#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1071#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1111#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1175#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1206[[nodiscard]]
inline std::string to_string(
const pwm::timer& t) {
1208#if SOC_LEDC_SUPPORT_HS_MODE
1209 if (t.speed_mode() == pwm::speed_mode::high_speed) {
1210 s =
"PWM_HS_TIMER_";
1217 s += std::to_string(t.idf_num());
1228[[nodiscard]]
inline std::string
to_string(pwm::channel ch) {
1229 return "PWM_CH_" + std::to_string(std::to_underlying(ch));
1239[[nodiscard]]
inline std::string
to_string(pwm::speed_mode m) {
1241 case pwm::speed_mode::low_speed:
1243#if SOC_LEDC_SUPPORT_HS_MODE
1244 case pwm::speed_mode::high_speed:
1245 return "high_speed";
1248 return "unknown(" + std::to_string(std::to_underlying(m)) +
")";
1254#include "sdkconfig.h"
1255#ifdef CONFIG_IDFXX_STD_FORMAT
1260struct formatter<
idfxx::pwm::timer> {
1261 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1263 template<
typename FormatContext>
1266 return std::copy(s.begin(), s.end(), ctx.out());
1270struct formatter<
idfxx::pwm::channel> {
1271 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1273 template<
typename FormatContext>
1276 return std::copy(s.begin(), s.end(), ctx.out());
1280struct formatter<
idfxx::pwm::speed_mode> {
1281 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
1283 template<
typename FormatContext>
1286 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.
friend result< output > try_start(idfxx::gpio, const timer::config &, const output_config &)
Starts PWM output with automatic allocation and custom output configuration.
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.
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.
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 used by this output.
idfxx::gpio gpio() const noexcept
Returns the GPIO pin used by 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.
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.
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++.
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.