diff --git a/src/modm/platform/timer/stm32/advanced.hpp.in b/src/modm/platform/timer/stm32/advanced.hpp.in index 94da70daca..eb04947d31 100644 --- a/src/modm/platform/timer/stm32/advanced.hpp.in +++ b/src/modm/platform/timer/stm32/advanced.hpp.in @@ -17,13 +17,12 @@ #ifndef MODM_STM32_TIMER_{{ id }}_HPP #define MODM_STM32_TIMER_{{ id }}_HPP +#include +#include #include "advanced_base.hpp" #include -namespace modm -{ - -namespace platform +namespace modm::platform { /** @@ -76,6 +75,9 @@ namespace platform class Timer{{ id }} : public AdvancedControlTimer { public: + // This type is the internal size of the counter. + using Value = uint16_t; + template< class... Signals > static void connect() @@ -149,34 +151,51 @@ public: TIM{{ id }}->PSC = prescaler - 1; } + static uint16_t + getPrescaler() + { + return TIM{{ id }}->PSC + 1; + } + static inline void - setOverflow(uint16_t overflow) + setOverflow(Value overflow) { TIM{{ id }}->ARR = overflow; } - template - static uint16_t - setPeriod(uint32_t microseconds, bool autoApply = true) + static inline Value + getOverflow() { - // This will be inaccurate for non-smooth frequencies (last six digits - // unequal to zero) - uint32_t cycles = microseconds * (SystemClock::Timer{{ id }} / 1'000'000UL); - uint16_t prescaler = (cycles + 65'535) / 65'536; // always round up - uint16_t overflow = cycles / prescaler; + return TIM{{ id }}->ARR; + } - overflow = overflow - 1; // e.g. 36'000 cycles are from 0 to 35'999 + template + static Value + setPeriod(std::chrono::duration duration, bool autoApply = true) + { + // This will be inaccurate for non-smooth frequencies (last six digits unequal to zero) + const uint32_t cycles = duration.count() * SystemClock::Timer{{ id }} * Period::num / Period::den; + const uint16_t prescaler = (cycles + std::numeric_limits::max() - 1) / std::numeric_limits::max(); // always round up + const Value overflow = cycles / prescaler - 1; setPrescaler(prescaler); setOverflow(overflow); - if (autoApply) { - // Generate Update Event to apply the new settings for ARR + // Generate Update Event to apply the new settings for ARR + if (autoApply) TIM{{ id }}->EGR |= TIM_EGR_UG; - } return overflow; -} + } + + // DEPRECATE: 2023q2 + template + [[deprecated("Pass microseconds as std::chrono::duration: setPeriod( {microseconds}us ) instead!")]] + static Value + setPeriod(uint32_t microseconds, bool autoApply = true) + { + return setPeriod(std::chrono::microseconds(microseconds), autoApply); + } static inline void applyAndReset() @@ -191,14 +210,14 @@ public: TIM{{ id }}->EGR |= static_cast(ev); } - static inline uint16_t + static inline Value getValue() { return TIM{{ id }}->CNT; } static inline void - setValue(uint16_t value) + setValue(Value value) { TIM{{ id }}->CNT = value; } @@ -314,7 +333,7 @@ public: static void configureOutputChannel(uint32_t channel, OutputCompareMode mode, - uint16_t compareValue); + Value compareValue); // TODO: Maybe add some functionality from the configureOutput // function below... @@ -361,7 +380,7 @@ public: configureOutputChannel(uint32_t channel, uint32_t modeOutputPorts); static inline void - setCompareValue(uint32_t channel, uint16_t value) + setCompareValue(uint32_t channel, Value value) { %% if advanced_extended if(channel <= 4) { @@ -376,7 +395,7 @@ public: %% endif } - static inline uint16_t + static inline Value getCompareValue(uint32_t channel) { return *(&TIM{{ id }}->CCR1 + (channel - 1)); @@ -438,8 +457,6 @@ public: } }; -} // namespace platform - -} // namespace modm +} // namespace modm::platform #endif // MODM_STM32_TIMER_{{ id }}_HPP diff --git a/src/modm/platform/timer/stm32/basic.hpp.in b/src/modm/platform/timer/stm32/basic.hpp.in index e8732a294f..20df7d6226 100644 --- a/src/modm/platform/timer/stm32/basic.hpp.in +++ b/src/modm/platform/timer/stm32/basic.hpp.in @@ -19,10 +19,7 @@ #include "basic_base.hpp" #include -namespace modm -{ - -namespace platform +namespace modm::platform { /** @@ -56,6 +53,9 @@ namespace platform class Timer{{ id }} : public BasicTimer { public: + // This type is the internal size of the counter. + using Value = uint16_t; + template< class... Signals > static void connect() @@ -93,34 +93,52 @@ public: TIM{{ id }}->PSC = prescaler - 1; } + static uint16_t + getPrescaler() + { + return TIM{{ id }}->PSC + 1; + } + static inline void - setOverflow(uint16_t overflow) + setOverflow(Value overflow) { TIM{{ id }}->ARR = overflow; } - template - static uint16_t - setPeriod(uint32_t microseconds, bool autoApply = true) + static inline Value + getOverflow() { - // This will be inaccurate for non-smooth frequencies (last six digits - // unequal to zero) - uint32_t cycles = microseconds * (SystemClock::Timer{{ id }} / 1'000'000UL); - uint16_t prescaler = (cycles + 65'535) / 65'536; // always round up - uint16_t overflow = cycles / prescaler; + return TIM{{ id }}->ARR; + } + + template + static Value + setPeriod(std::chrono::duration duration, bool autoApply = true) + { + // This will be inaccurate for non-smooth frequencies (last six digits unequal to zero) + const uint32_t cycles = duration.count() * SystemClock::Timer{{ id }} * Period::num / Period::den; + const uint16_t prescaler = (cycles + std::numeric_limits::max() - 1) / std::numeric_limits::max(); // always round up + const Value overflow = cycles / prescaler - 1; - overflow = overflow - 1; // e.g. 36'000 cycles are from 0 to 35'999 setPrescaler(prescaler); setOverflow(overflow); - if (autoApply) { - // Generate Update Event to apply the new settings for ARR + // Generate Update Event to apply the new settings for ARR + if (autoApply) TIM{{ id }}->EGR |= TIM_EGR_UG; - } return overflow; } + // DEPRECATE: 2023q2 + template + [[deprecated("Pass microseconds as std::chrono::duration: setPeriod( {microseconds}us ) instead!")]] + static Value + setPeriod(uint32_t microseconds, bool autoApply = true) + { + return setPeriod(std::chrono::microseconds(microseconds), autoApply); + } + static inline void applyAndReset() { @@ -128,14 +146,14 @@ public: TIM{{ id }}->EGR |= TIM_EGR_UG; } - static inline uint16_t + static inline Value getValue() { return TIM{{ id }}->CNT; } static inline void - setValue(uint16_t value) + setValue(Value value) { TIM{{ id }}->CNT = value; } @@ -170,8 +188,6 @@ public: } }; -} // namespace platform - -} // namespace modm +} // namespace modm::platform #endif // MODM_STM32_TIMER_{{ id }}_HPP diff --git a/src/modm/platform/timer/stm32/basic_base.hpp.in b/src/modm/platform/timer/stm32/basic_base.hpp.in index 06c89753ed..0757e24f4a 100644 --- a/src/modm/platform/timer/stm32/basic_base.hpp.in +++ b/src/modm/platform/timer/stm32/basic_base.hpp.in @@ -13,6 +13,8 @@ #ifndef MODM_STM32_TIMER_BASIC_BASE_HPP #define MODM_STM32_TIMER_BASIC_BASE_HPP +#include +#include #include #include "../device.hpp" #include @@ -46,6 +48,9 @@ public: MODM_FLAGS32(InterruptFlag); public: + // This type is the internal size of the counter. + using Value = uint16_t; + /** * Enables the clock for the timer and resets all settings * @@ -101,6 +106,12 @@ public: static inline void setPrescaler(uint16_t prescaler); + /** + * Get current prescaler + */ + static inline uint16_t + getPrescaler(); + /** * Set overflow. * @@ -112,15 +123,21 @@ public: * @see applyAndReset() */ static inline void - setOverflow(uint16_t overflow); + setOverflow(Value overflow); /** - * Set period in microseconds + * Get current overflow + */ + static inline Value + getOverflow(); + + /** + * Set Timer period * * Changes prescaler and overflow values. * Takes effect at next update event. * - * @param microseconds Requested period in microseconds + * @param duration Requested duration of period * @param autoApply Update the new value immediately and * reset the counter value. * @@ -128,8 +145,9 @@ public: * * @see applyAndReset() */ - static uint16_t - setPeriod(uint32_t microseconds, bool autoApply = true); + template + static Value + setPeriod(std::chrono::duration duration, bool autoApply = true); /** * @brief Reset the counter, and update the prescaler and @@ -155,14 +173,14 @@ public: /** * Get the counter value */ - static inline uint16_t + static inline Value getValue(); /** * Set a new counter value */ static inline void - setValue(uint16_t value); + setValue(Value value); /** * Enables or disables the Interrupt Vector. diff --git a/src/modm/platform/timer/stm32/general_purpose.hpp.in b/src/modm/platform/timer/stm32/general_purpose.hpp.in index 20fb015152..517a3e3f11 100644 --- a/src/modm/platform/timer/stm32/general_purpose.hpp.in +++ b/src/modm/platform/timer/stm32/general_purpose.hpp.in @@ -17,12 +17,12 @@ #ifndef MODM_STM32_TIMER_{{ id }}_HPP #define MODM_STM32_TIMER_{{ id }}_HPP +#include +#include #include "general_purpose_base.hpp" #include -namespace modm -{ -namespace platform +namespace modm::platform { /** * General Purpose Timer {{ id }} @@ -110,12 +110,13 @@ public: // This type is the internal size of the counter. %% if id in [2, 5] and (target["family"] in ["f2", "f3", "f4", "f7", "l1", "l4", "g4"]) // Timer 2 and 5 are the only one which have the size of 32 bit - typedef uint32_t Value; + using Value = uint32_t; %% else - typedef uint16_t Value; + using Value = uint16_t; %% endif + template< class... Signals > static void connect() @@ -167,7 +168,7 @@ public: static uint16_t getPrescaler() { - return (TIM{{ id }}->PSC + 1); + return TIM{{ id }}->PSC + 1; } static inline void @@ -176,29 +177,40 @@ public: TIM{{ id }}->ARR = overflow; } - template - static Value - setPeriod(uint32_t microseconds, bool autoApply = true) + static inline Value + getOverflow() { - // This will be inaccurate for non-smooth frequencies (last six digits - // unequal to zero) - uint32_t cycles = microseconds * (SystemClock::Timer{{ id }} / 1'000'000UL); - uint16_t prescaler = (cycles + 65'535) / 65'536; // always round up - Value overflow = cycles / prescaler; + return TIM{{ id }}->ARR; + } - overflow = overflow - 1; // e.g. 36'000 cycles are from 0 to 35'999 + template + static Value + setPeriod(std::chrono::duration duration, bool autoApply = true) + { + // This will be inaccurate for non-smooth frequencies (last six digits unequal to zero) + const uint32_t cycles = duration.count() * SystemClock::Timer{{ id }} * Period::num / Period::den; + const uint16_t prescaler = (cycles + std::numeric_limits::max() - 1) / std::numeric_limits::max(); // always round up + const Value overflow = cycles / prescaler - 1; setPrescaler(prescaler); setOverflow(overflow); - if (autoApply) { - // Generate Update Event to apply the new settings for ARR + // Generate Update Event to apply the new settings for ARR + if (autoApply) TIM{{ id }}->EGR |= TIM_EGR_UG; - } return overflow; } + // DEPRECATE: 2023q2 + template + [[deprecated("Pass microseconds as std::chrono::duration: setPeriod( {microseconds}us ) instead!")]] + static Value + setPeriod(uint32_t microseconds, bool autoApply = true) + { + return setPeriod(std::chrono::microseconds(microseconds), autoApply); + } + /* Returns the frequency of the timer */ template static uint32_t @@ -543,8 +555,6 @@ public: } }; -} // namespace platform - -} // namespace modm +} // namespace modm::platform #endif // MODM_STM32_TIMER_{{ id }}_HPP