From b5f55afcc9c5807ae015a4a07a5b7ad20af54ecc Mon Sep 17 00:00:00 2001 From: Christopher Kormanyos Date: Sun, 25 Feb 2024 09:47:06 +0100 Subject: [PATCH] Add/update port-based PWM class --- ref_app/ref_app.vcxproj | 1 + ref_app/ref_app.vcxproj.filters | 3 ++ ref_app/src/mcal/avr/mcal_benchmark.h | 10 ++-- ref_app/src/mcal/avr/mcal_pwm.cpp | 2 +- ref_app/src/mcal_pwm/mcal_pwm_base.h | 13 +++-- ref_app/src/mcal_pwm/mcal_pwm_port.h | 74 +++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 ref_app/src/mcal_pwm/mcal_pwm_port.h diff --git a/ref_app/ref_app.vcxproj b/ref_app/ref_app.vcxproj index 443f9ac74..14715873d 100644 --- a/ref_app/ref_app.vcxproj +++ b/ref_app/ref_app.vcxproj @@ -2388,6 +2388,7 @@ + diff --git a/ref_app/ref_app.vcxproj.filters b/ref_app/ref_app.vcxproj.filters index fe13ee103..e1c051869 100644 --- a/ref_app/ref_app.vcxproj.filters +++ b/ref_app/ref_app.vcxproj.filters @@ -2271,6 +2271,9 @@ src\util\utility + + src\mcal_pwm + diff --git a/ref_app/src/mcal/avr/mcal_benchmark.h b/ref_app/src/mcal/avr/mcal_benchmark.h index 54969540e..c34886ba6 100644 --- a/ref_app/src/mcal/avr/mcal_benchmark.h +++ b/ref_app/src/mcal/avr/mcal_benchmark.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2014 - 2023. +// Copyright Christopher Kormanyos 2014 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,10 +17,10 @@ { namespace benchmark { - typedef mcal::port::port_pin benchmark_port_type; + using benchmark_port_type = mcal::port::port_pin; } } diff --git a/ref_app/src/mcal/avr/mcal_pwm.cpp b/ref_app/src/mcal/avr/mcal_pwm.cpp index 5ad7b95bd..2054cd193 100644 --- a/ref_app/src/mcal/avr/mcal_pwm.cpp +++ b/ref_app/src/mcal/avr/mcal_pwm.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2007 - 2023. +// Copyright Christopher Kormanyos 2007 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/ref_app/src/mcal_pwm/mcal_pwm_base.h b/ref_app/src/mcal_pwm/mcal_pwm_base.h index 475859de8..5bae70e7f 100644 --- a/ref_app/src/mcal_pwm/mcal_pwm_base.h +++ b/ref_app/src/mcal_pwm/mcal_pwm_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Copyright Christopher Kormanyos 2020 - 2022. +// Copyright Christopher Kormanyos 2020 - 2024. // Distributed under the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,19 +17,22 @@ class pwm_base : private util::noncopyable { public: + using duty_type = std::uint16_t; + virtual ~pwm_base() noexcept = default; virtual auto init() noexcept -> bool = 0; - virtual auto set_duty(const std::uint16_t duty_cycle) noexcept -> void { my_duty_cycle = duty_cycle; } + virtual auto set_duty(const duty_type duty_cycle) noexcept -> void { my_duty_cycle = duty_cycle; } - auto get_duty() const noexcept -> std::uint16_t { return my_duty_cycle; } + auto get_duty() const noexcept -> duty_type { return my_duty_cycle; } protected: - pwm_base() noexcept = default; + explicit pwm_base(const duty_type initial_duty = static_cast(UINT8_C(0))) noexcept + : my_duty_cycle(initial_duty) { } private: - std::uint16_t my_duty_cycle { }; + duty_type my_duty_cycle { }; }; } // namespace pwm diff --git a/ref_app/src/mcal_pwm/mcal_pwm_port.h b/ref_app/src/mcal_pwm/mcal_pwm_port.h new file mode 100644 index 000000000..5ce686fec --- /dev/null +++ b/ref_app/src/mcal_pwm/mcal_pwm_port.h @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright Christopher Kormanyos 2007 - 2024. +// Distributed under the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef MCAL_PWM_PORT_2023_08_23_H + #define MCAL_PWM_PORT_2023_08_23_H + + #include + + namespace mcal { namespace pwm { + + // A software PWM template for a port-pin having the standard + // port interface for ref_app. The default resolution is 100 ticks. + + template(UINT8_C(100))> + class pwm_port : public pwm_base + { + private: + using base_class_type = pwm_base; + using port_pin_type = PortPinType; + + public: + using base_class_type::duty_type; + + explicit pwm_port(const duty_type initial_duty = static_cast(UINT8_C(0))) + : base_class_type(initial_duty), + my_duty_shadow(initial_duty) + { + port_pin_type::set_pin_low(); + port_pin_type::set_direction_output(); + } + + ~pwm_port() noexcept override = default; + + auto init() noexcept -> bool override + { + return true; + } + + auto set_duty(const duty_type duty_cycle) noexcept -> void override { my_duty_shadow = duty_cycle; } + + static constexpr auto get_resolution() noexcept -> duty_type { return MyResolution; } + + auto service() noexcept -> void + { + // Increment the cycle counter. + ++my_cycle_counter; + + ((my_cycle_counter <= base_class_type::get_duty()) ? port_pin_type::set_pin_high() : port_pin_type::set_pin_low()); + + if(my_cycle_counter == get_resolution()) + { + // Latch the duty cycle from the shadow register. + // This is done at the end of the running cycle. + base_class_type::set_duty(my_duty_shadow); + + // Reset the cycle counter for a new PWM period. + my_cycle_counter = static_cast(UINT8_C(0)); + } + } + + private: + duty_type my_cycle_counter { }; + duty_type my_duty_shadow { }; + }; + + } // namespace pwm + } // namespace mcal + +#endif // MCAL_PWM_PORT_2023_08_23_H