Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,4 @@ Exception-based methods should not have abbreviated documentation. Inline implem
- Compile-time validation with `static_assert` for type properties and enum values
- Runtime tests use ESP-IDF Unity framework: `TEST_CASE("name", "[tag]")`
- Tests verify enum values match ESP-IDF constants
- **Do not use GPIO 19 or GPIO 20 in tests** — these are the USB D-/D+ pins on ESP32-S3 and configuring them for peripheral output (e.g., LEDC) hangs when USB-JTAG/Serial is active
46 changes: 25 additions & 21 deletions components/idfxx_pwm/include/idfxx/pwm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,8 @@ class timer {

constexpr bool operator==(const timer& other) const = default;

/** @cond INTERNAL */
/** @brief Returns the timer number (0-3). */
[[nodiscard]] constexpr int idf_num() const noexcept { return _num; }
/** @endcond */
[[nodiscard]] constexpr unsigned int num() const noexcept { return _num; }

/** @brief Returns the speed mode. */
[[nodiscard]] constexpr enum speed_mode speed_mode() const noexcept { return _speed_mode; }
Expand Down Expand Up @@ -425,11 +423,11 @@ class timer {
private:
friend result<output> try_start(idfxx::gpio, const config&, const output_config&);

constexpr timer(int num, enum speed_mode mode) noexcept
constexpr timer(unsigned int num, enum speed_mode mode) noexcept
: _num(num)
, _speed_mode(mode) {}

int _num;
unsigned int _num;
enum speed_mode _speed_mode;
};

Expand Down Expand Up @@ -709,11 +707,22 @@ class output {
output(output&& other) noexcept;
output& operator=(output&& other) noexcept;

/** @brief Returns the channel slot used by this output. */
/**
* @brief Returns the timer that was bound to this output.
*
* @note This output may no longer be driving the channel.
*/
[[nodiscard]] class timer timer() const noexcept { return _timer; }

/**
* @brief Returns the channel slot that was bound to this output.
*
* @note This output may no longer be driving the channel.
*/
[[nodiscard]] enum channel channel() const noexcept { return _channel; }

/** @brief Returns the GPIO pin used by this output. */
[[nodiscard]] idfxx::gpio gpio() const noexcept { return _gpio; }
/** @brief Returns true if the output is still actively driving the channel. */
[[nodiscard]] bool is_active() const noexcept;

/** @brief Returns the maximum duty ticks for the configured resolution. */
[[nodiscard]] uint32_t ticks_max() const noexcept;
Expand Down Expand Up @@ -1138,20 +1147,15 @@ class output {
*/
enum channel release() noexcept;

/** @cond INTERNAL */
[[nodiscard]] static result<output>
make(const timer& tmr, enum channel ch, idfxx::gpio gpio, const output_config& cfg);

[[nodiscard]] static result<output> make(const timer& tmr, enum channel ch, idfxx::gpio gpio);
/** @endcond */

private:
friend result<output>
try_start(idfxx::gpio gpio, const class timer& tmr, enum channel ch, const output_config& cfg);
friend result<output> try_start(idfxx::gpio, const timer::config&, const output_config&);

explicit output(class timer tmr, enum channel ch, idfxx::gpio gpio, uint32_t gen) noexcept;

[[nodiscard]] static result<output>
_make(const timer& tmr, enum channel ch, idfxx::gpio gpio, const output_config& cfg);
_make(idfxx::gpio gpio, const class timer& tmr, enum channel ch, const output_config& cfg);

explicit output(class timer tmr, enum channel ch, uint32_t gen, uint32_t duty_ticks) noexcept;

[[nodiscard]] result<void> _try_set_pulse_width(std::chrono::nanoseconds width);

Expand All @@ -1164,12 +1168,12 @@ class output {
[[nodiscard]] result<void>
_try_fade_to_duty(uint32_t target_duty, std::chrono::milliseconds duration, enum fade_mode mode);

void _cleanup() noexcept;
void _delete() noexcept;

class timer _timer;
enum channel _channel;
idfxx::gpio _gpio;
std::optional<uint32_t> _gen;
uint32_t _duty_ticks = 0;
};

#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
Expand Down Expand Up @@ -1214,7 +1218,7 @@ namespace idfxx {
#else
s = "PWM_TIMER_";
#endif
s += std::to_string(t.idf_num());
s += std::to_string(t.num());
return s;
}

Expand Down
Loading
Loading