idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
pwm.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
24#include <idfxx/error>
25#include <idfxx/gpio>
26#include <idfxx/intr_alloc>
27
28#include <algorithm>
29#include <chrono>
30#include <frequency/frequency>
31#include <functional>
32#include <memory>
33#include <optional>
34#include <span>
35#include <string>
36#include <utility>
37
38namespace idfxx::pwm {
39
40// ======================================================================
41// Enums
42// ======================================================================
43
51enum class speed_mode : int {
52 low_speed = 0,
53#if SOC_LEDC_SUPPORT_HS_MODE
54 high_speed,
55#endif
56};
57
65enum class channel : int {
66 ch_0 = 0,
67 ch_1,
68 ch_2,
69 ch_3,
70 ch_4,
71 ch_5,
72#if SOC_LEDC_CHANNEL_NUM > 6
73 ch_6,
74#endif
75#if SOC_LEDC_CHANNEL_NUM > 7
76 ch_7,
77#endif
78};
79
87enum class clk_source : int {
88 auto_select = 0,
89#if SOC_LEDC_SUPPORT_APB_CLOCK
90 apb,
91#endif
92#if SOC_LEDC_SUPPORT_REF_TICK
93 ref_tick,
94#endif
95#if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
96 pll_div,
97#endif
98#if SOC_LEDC_SUPPORT_XTAL_CLOCK
99 xtal,
100#endif
101};
102
107enum class fade_mode : int {
108 no_wait = 0,
109 wait_done,
110};
111
116enum class sleep_mode : int {
117 no_alive_no_pd = 0,
119 keep_alive,
120};
121
128 uint32_t cycle_num;
129 uint32_t scale;
130 uint32_t step_num;
131};
132
133// ======================================================================
134// Forward declarations
135// ======================================================================
136
138class output;
139struct output_config;
140template<int N, speed_mode M>
141struct timer_constant;
144// ======================================================================
145// timer (value type)
146// ======================================================================
147
169class timer {
170 template<int N, speed_mode M>
171 friend struct timer_constant;
172 friend std::optional<timer> get_timer(enum channel, enum speed_mode);
173
174public:
179 struct config {
180 freq::hertz frequency{0};
181 uint8_t resolution_bits = 13;
183 };
184
185 timer(const timer&) = default;
186 timer& operator=(const timer&) = default;
187 timer(timer&&) = default;
188 timer& operator=(timer&&) = default;
189
190 constexpr bool operator==(const timer& other) const = default;
191
193 [[nodiscard]] constexpr unsigned int num() const noexcept { return _num; }
194
196 [[nodiscard]] constexpr enum speed_mode speed_mode() const noexcept { return _speed_mode; }
197
198#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
214 void configure(const struct config& cfg) { unwrap(try_configure(cfg)); }
215
226 void configure(freq::hertz frequency, uint8_t resolution_bits = 13) {
228 }
229#endif
230
243 [[nodiscard]] result<void> try_configure(const struct config& cfg);
244
254 [[nodiscard]] result<void> try_configure(freq::hertz frequency, uint8_t resolution_bits = 13) {
255 return try_configure({.frequency = frequency, .resolution_bits = resolution_bits});
256 }
257
266 [[nodiscard]] bool is_configured() const noexcept;
267
275 [[nodiscard]] uint8_t resolution_bits() const noexcept;
276
284 [[nodiscard]] uint32_t ticks_max() const noexcept;
285
294 [[nodiscard]] freq::hertz frequency() const;
295
303 [[nodiscard]] std::chrono::nanoseconds period() const;
304
313 [[nodiscard]] std::chrono::nanoseconds tick_period() const;
314
315#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
326#endif
327
339 [[nodiscard]] result<void> try_set_frequency(freq::hertz frequency);
340
341#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
358 template<typename Rep, typename Period>
359 void set_period(const std::chrono::duration<Rep, Period>& period) {
361 }
362#endif
363
377 template<typename Rep, typename Period>
378 [[nodiscard]] result<void> try_set_period(const std::chrono::duration<Rep, Period>& period) {
379 auto ns = std::chrono::ceil<std::chrono::nanoseconds>(period).count();
380 if (ns <= 0) {
381 return error(errc::invalid_arg);
382 }
383 return try_set_frequency(freq::hertz{1'000'000'000 / ns});
384 }
385
386#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
393 void pause() { unwrap(try_pause()); }
394#endif
395
401 [[nodiscard]] result<void> try_pause();
402
403#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
410 void resume() { unwrap(try_resume()); }
411#endif
412
418 [[nodiscard]] result<void> try_resume();
419
420#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
427 void reset() { unwrap(try_reset()); }
428#endif
429
435 [[nodiscard]] result<void> try_reset();
436
437private:
439
440 constexpr timer(unsigned int num, enum speed_mode mode) noexcept
441 : _num(num)
442 , _speed_mode(mode) {}
443
444 unsigned int _num;
445 enum speed_mode _speed_mode;
446};
447
449template<int N, speed_mode M>
450struct timer_constant {
451 static_assert(N >= 0 && N < SOC_LEDC_TIMER_NUM, "Invalid PWM timer number");
452 static constexpr timer value{N, M};
453};
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;
466
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;
472#endif
// end of Timer Constants
474
475// ======================================================================
476// start / try_start — free functions for starting PWM output
477// ======================================================================
478
489
490#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
519[[nodiscard]] output start(idfxx::gpio gpio, const timer& tmr, enum channel ch);
520
523[[nodiscard]] output start(idfxx::gpio gpio, const timer& tmr, enum channel ch, const output_config& cfg);
524
545[[nodiscard]] output start(idfxx::gpio gpio, const timer::config& cfg);
546
549[[nodiscard]] output start(idfxx::gpio gpio, const timer::config& cfg, const output_config& out_cfg);
550
553void stop(
554 enum channel ch,
557);
558#endif
559
587[[nodiscard]] result<output> try_start(idfxx::gpio gpio, const timer& tmr, enum channel ch);
588
602[[nodiscard]] result<output> try_start(idfxx::gpio gpio, const timer& tmr, enum channel ch, const output_config& cfg);
603
629
642[[nodiscard]] result<output> try_start(idfxx::gpio gpio, const timer::config& cfg, const output_config& out_cfg);
643
652[[nodiscard]] bool is_active(enum channel ch, enum speed_mode mode = speed_mode::low_speed);
653
662[[nodiscard]] std::optional<timer> get_timer(enum channel ch, enum speed_mode mode = speed_mode::low_speed);
663
677 enum channel ch,
680);
681
682// ======================================================================
683// output (RAII, move-only)
684// ======================================================================
685
710class output {
711public:
718
719 output(const output&) = delete;
720 output& operator=(const output&) = delete;
721 output(output&& other) noexcept;
722 output& operator=(output&& other) noexcept;
723
729 [[nodiscard]] class timer timer() const noexcept { return _timer; }
730
736 [[nodiscard]] enum channel channel() const noexcept { return _channel; }
737
739 [[nodiscard]] bool is_active() const noexcept;
740
742 [[nodiscard]] uint32_t ticks_max() const noexcept;
743
749 [[nodiscard]] float duty() const;
750
758 [[nodiscard]] uint32_t duty_ticks() const;
759
760#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
771#endif
772
784 [[nodiscard]] result<void> try_set_duty(float duty);
785
786#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
797
808 void set_duty_ticks(uint32_t duty, uint32_t hpoint) { unwrap(try_set_duty_ticks(duty, hpoint)); }
809#endif
810
819 [[nodiscard]] result<void> try_set_duty_ticks(uint32_t duty);
820
830 [[nodiscard]] result<void> try_set_duty_ticks(uint32_t duty, uint32_t hpoint);
831
837 [[nodiscard]] std::chrono::nanoseconds pulse_width() const;
838
839#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
854 template<typename Rep, typename Period>
855 void set_pulse_width(const std::chrono::duration<Rep, Period>& width) {
857 }
858#endif
859
870 template<typename Rep, typename Period>
871 [[nodiscard]] result<void> try_set_pulse_width(const std::chrono::duration<Rep, Period>& width) {
872 return _try_set_pulse_width(std::chrono::ceil<std::chrono::nanoseconds>(width));
873 }
874
875#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
889 template<typename Rep, typename Period>
891 float target,
892 const std::chrono::duration<Rep, Period>& duration,
893 enum fade_mode mode = fade_mode::no_wait
894 ) {
895 unwrap(try_fade_to(target, duration, mode));
896 }
897#endif
898
914 template<typename Rep, typename Period>
916 float target,
917 const std::chrono::duration<Rep, Period>& duration,
918 enum fade_mode mode = fade_mode::no_wait
919 ) {
920 return _try_fade_to_duty(
921 static_cast<uint32_t>(std::clamp(target, 0.0f, 1.0f) * static_cast<float>(ticks_max())),
922 std::chrono::ceil<std::chrono::milliseconds>(duration),
923 mode
924 );
925 }
926
927#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
941 template<typename Rep, typename Period>
943 uint32_t target_duty,
944 const std::chrono::duration<Rep, Period>& duration,
945 enum fade_mode mode = fade_mode::no_wait
946 ) {
947 unwrap(try_fade_to_duty_ticks(target_duty, duration, mode));
948 }
949#endif
950
966 template<typename Rep, typename Period>
968 uint32_t target_duty,
969 const std::chrono::duration<Rep, Period>& duration,
970 enum fade_mode mode = fade_mode::no_wait
971 ) {
972 return _try_fade_to_duty(target_duty, std::chrono::ceil<std::chrono::milliseconds>(duration), mode);
973 }
974
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,
995 enum fade_mode mode = fade_mode::no_wait
996 ) {
997 unwrap(try_fade_to_pulse_width(target_width, duration, mode));
998 }
999#endif
1000
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,
1022 enum fade_mode mode = fade_mode::no_wait
1023 ) {
1024 return _try_fade_to_pulse_width(
1025 std::chrono::ceil<std::chrono::nanoseconds>(target_width),
1026 std::chrono::ceil<std::chrono::milliseconds>(duration),
1027 mode
1028 );
1029 }
1030
1031#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1044 void
1045 fade_with_step(uint32_t target_duty, uint32_t scale, uint32_t cycle_num, enum fade_mode mode = fade_mode::no_wait) {
1046 unwrap(try_fade_with_step(target_duty, scale, cycle_num, mode));
1047 }
1048#endif
1049
1065 uint32_t target_duty,
1066 uint32_t scale,
1067 uint32_t cycle_num,
1068 enum fade_mode mode = fade_mode::no_wait
1069 );
1070
1071#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
1072#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1086 void multi_fade(uint32_t start_duty, std::span<const fade_param> steps, enum fade_mode mode = fade_mode::no_wait) {
1087 unwrap(try_multi_fade(start_duty, steps, mode));
1088 }
1089#endif
1090
1106 [[nodiscard]] result<void>
1107 try_multi_fade(uint32_t start_duty, std::span<const fade_param> steps, enum fade_mode mode = fade_mode::no_wait);
1108
1109#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1120 [[nodiscard]] fade_param read_fade_param(uint32_t range) const { return unwrap(try_read_fade_param(range)); }
1121#endif
1122
1131 [[nodiscard]] result<fade_param> try_read_fade_param(uint32_t range) const;
1132
1133#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1152 template<typename Rep, typename Period>
1153 [[nodiscard]] std::vector<fade_param> fill_multi_fade_params(
1154 uint32_t start_duty,
1155 uint32_t end_duty,
1156 uint32_t linear_phases,
1157 const std::chrono::duration<Rep, Period>& max_fade_time,
1158 uint32_t (*gamma_correction)(uint32_t)
1159 ) {
1160 return unwrap(try_fill_multi_fade_params(start_duty, end_duty, linear_phases, max_fade_time, gamma_correction));
1161 }
1162#endif
1163
1179 template<typename Rep, typename Period>
1180 [[nodiscard]] result<std::vector<fade_param>> try_fill_multi_fade_params(
1181 uint32_t start_duty,
1182 uint32_t end_duty,
1183 uint32_t linear_phases,
1184 const std::chrono::duration<Rep, Period>& max_fade_time,
1185 uint32_t (*gamma_correction)(uint32_t)
1186 ) {
1187 return _try_fill_multi_fade_params(
1188 start_duty,
1189 end_duty,
1190 linear_phases,
1191 std::chrono::ceil<std::chrono::milliseconds>(max_fade_time),
1192 gamma_correction
1193 );
1194 }
1195#endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
1196
1197#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1210 void register_fade_end_callback(std::move_only_function<bool() const> callback) {
1211 unwrap(try_register_fade_end_callback(std::move(callback)));
1212 }
1213#endif
1214
1227 [[nodiscard]] result<void> try_register_fade_end_callback(std::move_only_function<bool() const> callback);
1228
1229#if SOC_LEDC_SUPPORT_FADE_STOP
1230#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1239 void fade_stop() { unwrap(try_fade_stop()); }
1240#endif
1241
1249 result<void> try_fade_stop();
1250#endif
1251
1252#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1264 static void
1268#endif
1269
1282 [[nodiscard]] static result<void>
1284
1291
1292#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1301#endif
1302
1310
1320 enum channel release() noexcept;
1321
1322private:
1323 friend result<output>
1324 try_start(idfxx::gpio gpio, const class timer& tmr, enum channel ch, const output_config& cfg);
1325 friend result<output> try_start(idfxx::gpio, const timer::config&, const output_config&);
1326
1327 [[nodiscard]] static result<output>
1328 _make(idfxx::gpio gpio, const class timer& tmr, enum channel ch, const output_config& cfg);
1329
1330 explicit output(class timer tmr, enum channel ch, uint32_t gen, uint32_t duty_ticks) noexcept;
1331
1332 [[nodiscard]] result<void> _try_set_pulse_width(std::chrono::nanoseconds width);
1333
1334 [[nodiscard]] result<void> _try_fade_to_pulse_width(
1335 std::chrono::nanoseconds target_width,
1336 std::chrono::milliseconds duration,
1337 enum fade_mode mode
1338 );
1339
1340 [[nodiscard]] result<void>
1341 _try_fade_to_duty(uint32_t target_duty, std::chrono::milliseconds duration, enum fade_mode mode);
1342
1343#if SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
1344 [[nodiscard]] result<std::vector<fade_param>> _try_fill_multi_fade_params(
1345 uint32_t start_duty,
1346 uint32_t end_duty,
1347 uint32_t linear_phases,
1348 std::chrono::milliseconds max_fade_time,
1349 uint32_t (*gamma_correction)(uint32_t)
1350 );
1351#endif
1352
1353 void _delete() noexcept;
1354
1355 class timer _timer;
1356 enum channel _channel;
1357 std::optional<uint32_t> _gen;
1358 uint32_t _duty_ticks = 0;
1359 std::unique_ptr<std::move_only_function<bool() const>> _fade_cb;
1360};
1361
1362#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
1363inline output start(idfxx::gpio gpio, const timer& tmr, enum channel ch) {
1364 return unwrap(try_start(gpio, tmr, ch));
1365}
1366inline output start(idfxx::gpio gpio, const timer& tmr, enum channel ch, const output_config& cfg) {
1367 return unwrap(try_start(gpio, tmr, ch, cfg));
1368}
1370 return unwrap(try_start(gpio, cfg));
1371}
1372inline output start(idfxx::gpio gpio, const timer::config& cfg, const output_config& out_cfg) {
1373 return unwrap(try_start(gpio, cfg, out_cfg));
1374}
1375inline void stop(enum channel ch, enum speed_mode mode, idfxx::gpio::level idle_level) {
1376 unwrap(try_stop(ch, mode, idle_level));
1377}
1378#endif
1379
// end of idfxx_pwm
1381
1382} // namespace idfxx::pwm
1383
1384namespace idfxx {
1385
1393[[nodiscard]] inline std::string to_string(const pwm::timer& t) {
1394 std::string s;
1395#if SOC_LEDC_SUPPORT_HS_MODE
1396 if (t.speed_mode() == pwm::speed_mode::high_speed) {
1397 s = "PWM_HS_TIMER_";
1398 } else {
1399 s = "PWM_TIMER_";
1400 }
1401#else
1402 s = "PWM_TIMER_";
1403#endif
1404 s += std::to_string(t.num());
1405 return s;
1406}
1407
1415[[nodiscard]] inline std::string to_string(pwm::channel ch) {
1416 return "PWM_CH_" + std::to_string(std::to_underlying(ch));
1417}
1418
1426[[nodiscard]] inline std::string to_string(pwm::speed_mode m) {
1427 switch (m) {
1428 case pwm::speed_mode::low_speed:
1429 return "low_speed";
1430#if SOC_LEDC_SUPPORT_HS_MODE
1431 case pwm::speed_mode::high_speed:
1432 return "high_speed";
1433#endif
1434 default:
1435 return "unknown(" + std::to_string(std::to_underlying(m)) + ")";
1436 }
1437}
1438
1439} // namespace idfxx
1440
1441#include "sdkconfig.h"
1442#ifdef CONFIG_IDFXX_STD_FORMAT
1444#include <format>
1445namespace std {
1446template<>
1447struct formatter<idfxx::pwm::timer> {
1448 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
1449
1450 template<typename FormatContext>
1451 auto format(const idfxx::pwm::timer& t, FormatContext& ctx) const {
1452 auto s = idfxx::to_string(t);
1453 return std::copy(s.begin(), s.end(), ctx.out());
1454 }
1455};
1456template<>
1457struct formatter<idfxx::pwm::channel> {
1458 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
1459
1460 template<typename FormatContext>
1461 auto format(idfxx::pwm::channel ch, FormatContext& ctx) const {
1462 auto s = idfxx::to_string(ch);
1463 return std::copy(s.begin(), s.end(), ctx.out());
1464 }
1465};
1466template<>
1467struct formatter<idfxx::pwm::speed_mode> {
1468 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
1469
1470 template<typename FormatContext>
1471 auto format(idfxx::pwm::speed_mode m, FormatContext& ctx) const {
1472 auto s = idfxx::to_string(m);
1473 return std::copy(s.begin(), s.end(), ctx.out());
1474 }
1475};
1476} // namespace std
1478#endif // CONFIG_IDFXX_STD_FORMAT
A GPIO pin.
Definition gpio.hpp:62
level
GPIO output/input level.
Definition gpio.hpp:68
@ low
Logic low (0)
An active PWM output binding a timer, channel, and GPIO pin.
Definition pwm.hpp:710
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.
Definition pwm.hpp:915
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.
Definition pwm.hpp:967
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.
Definition pwm.hpp:942
result< void > try_set_pulse_width(const std::chrono::duration< Rep, Period > &width)
Sets the PWM duty cycle as a pulse width duration.
Definition pwm.hpp:871
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.
Definition pwm.hpp:796
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.
Definition pwm.hpp:1045
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.
Definition pwm.hpp:1210
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.
Definition pwm.hpp:1300
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.
Definition pwm.hpp:1019
static void install_fade_service(idfxx::intr_levels levels=intr_level_lowmed, idfxx::flags< intr_flag > flags={})
Installs the PWM fade service.
Definition pwm.hpp:1265
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.
Definition pwm.hpp:992
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.
Definition pwm.hpp:736
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.
Definition pwm.hpp:855
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.
Definition pwm.hpp:770
void set_duty_ticks(uint32_t duty, uint32_t hpoint)
Sets the PWM duty cycle in ticks with high point.
Definition pwm.hpp:808
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.
Definition pwm.hpp:890
A lightweight identifier for a hardware PWM timer.
Definition pwm.hpp:169
void configure(const struct config &cfg)
Configures the timer with the given parameters.
Definition pwm.hpp:214
result< void > try_configure(const struct config &cfg)
Configures the timer with the given parameters.
timer(timer &&)=default
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).
Definition pwm.hpp:193
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
Definition pwm.hpp:171
result< void > try_configure(freq::hertz frequency, uint8_t resolution_bits=13)
Configures the timer with frequency and resolution.
Definition pwm.hpp:254
constexpr enum speed_mode speed_mode() const noexcept
Returns the speed mode.
Definition pwm.hpp:196
void resume()
Resumes the timer counter.
Definition pwm.hpp:410
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.
Definition pwm.hpp:359
result< void > try_pause()
Pauses the timer counter.
result< void > try_resume()
Resumes the timer counter.
void pause()
Pauses the timer counter.
Definition pwm.hpp:393
void reset()
Resets the timer counter.
Definition pwm.hpp:427
void configure(freq::hertz frequency, uint8_t resolution_bits=13)
Configures the timer with frequency and resolution.
Definition pwm.hpp:226
result< void > try_reset()
Resets the timer counter.
void set_frequency(freq::hertz frequency)
Changes the timer frequency.
Definition pwm.hpp:325
result< void > try_set_period(const std::chrono::duration< Rep, Period > &period)
Changes the timer period.
Definition pwm.hpp:378
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.
Definition timer.hpp:41
std::string to_string(core_id c)
Returns a string representation of a CPU core identifier.
Definition cpu.hpp:52
constexpr timer timer_2
Definition pwm.hpp:464
constexpr timer timer_1
Definition pwm.hpp:463
constexpr timer timer_0
Definition pwm.hpp:462
constexpr timer timer_3
Definition pwm.hpp:465
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.
Definition pwm.hpp:116
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.
Definition pwm.hpp:51
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.
Definition pwm.hpp:1375
channel
PWM channel slot identifiers.
Definition pwm.hpp:65
output start(idfxx::gpio gpio, const timer &tmr, enum channel ch)
Starts PWM output on a GPIO pin.
Definition pwm.hpp:1363
fade_mode
Fade operation blocking mode.
Definition pwm.hpp:107
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.
Definition pwm.hpp:87
@ 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.
Definition adc.hpp:48
constexpr std::unexpected< std::error_code > error(E e) noexcept
Creates an unexpected error from an error code enum.
Definition error.hpp:187
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ invalid_arg
Invalid argument.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
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.
Definition pwm.hpp:126
bool increasing
Duty change direction: true = increase, false = decrease.
Definition pwm.hpp:127
uint32_t scale
Duty change per step.
Definition pwm.hpp:129
uint32_t cycle_num
Number of PWM cycles per step.
Definition pwm.hpp:128
uint32_t step_num
Total number of steps.
Definition pwm.hpp:130
Output configuration parameters.
Definition pwm.hpp:483
bool output_invert
Invert the output signal.
Definition pwm.hpp:486
float duty
Initial duty cycle ratio (0.0 to 1.0).
Definition pwm.hpp:484
int hpoint
High point in the PWM cycle.
Definition pwm.hpp:485
Timer configuration parameters.
Definition pwm.hpp:179
uint8_t resolution_bits
Duty resolution in bits (1 to SOC_LEDC_TIMER_BIT_WIDTH).
Definition pwm.hpp:181
freq::hertz frequency
PWM frequency.
Definition pwm.hpp:180