Skip to content

Commit

Permalink
using std::chrono on platform:Timer**::setPeriod()
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSaw committed Jun 12, 2022
1 parent 7b5827f commit 5ddcab3
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 76 deletions.
69 changes: 43 additions & 26 deletions src/modm/platform/timer/stm32/advanced.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
#ifndef MODM_STM32_TIMER_{{ id }}_HPP
#define MODM_STM32_TIMER_{{ id }}_HPP

#include <chrono>
#include <limits>
#include "advanced_base.hpp"
#include <modm/platform/gpio/connector.hpp>

namespace modm
{

namespace platform
namespace modm::platform
{

/**
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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<class SystemClock>
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<class SystemClock, class Rep, class Period>
static Value
setPeriod(std::chrono::duration<Rep, Period> 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<Value>::max() - 1) / std::numeric_limits<Value>::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<class SystemClock>
[[deprecated("Pass microseconds as std::chrono::duration: setPeriod( {microseconds}us ) instead!")]]
static Value
setPeriod(uint32_t microseconds, bool autoApply = true)
{
return setPeriod<SystemClock>(std::chrono::microseconds(microseconds), autoApply);
}

static inline void
applyAndReset()
Expand All @@ -191,14 +210,14 @@ public:
TIM{{ id }}->EGR |= static_cast<uint32_t>(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;
}
Expand Down Expand Up @@ -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...

Expand Down Expand Up @@ -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) {
Expand All @@ -376,7 +395,7 @@ public:
%% endif
}

static inline uint16_t
static inline Value
getCompareValue(uint32_t channel)
{
return *(&TIM{{ id }}->CCR1 + (channel - 1));
Expand Down Expand Up @@ -438,8 +457,6 @@ public:
}
};

} // namespace platform

} // namespace modm
} // namespace modm::platform

#endif // MODM_STM32_TIMER_{{ id }}_HPP
60 changes: 38 additions & 22 deletions src/modm/platform/timer/stm32/basic.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
#include "basic_base.hpp"
#include <modm/platform/gpio/connector.hpp>

namespace modm
{

namespace platform
namespace modm::platform
{

/**
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -93,49 +93,67 @@ 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<class SystemClock>
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<class SystemClock, class Rep, class Period>
static Value
setPeriod(std::chrono::duration<Rep, Period> 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<Value>::max() - 1) / std::numeric_limits<Value>::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<class SystemClock>
[[deprecated("Pass microseconds as std::chrono::duration: setPeriod( {microseconds}us ) instead!")]]
static Value
setPeriod(uint32_t microseconds, bool autoApply = true)
{
return setPeriod<SystemClock>(std::chrono::microseconds(microseconds), autoApply);
}

static inline void
applyAndReset()
{
// Generate Update Event to apply the new settings for ARR
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;
}
Expand Down Expand Up @@ -170,8 +188,6 @@ public:
}
};

} // namespace platform

} // namespace modm
} // namespace modm::platform

#endif // MODM_STM32_TIMER_{{ id }}_HPP
32 changes: 25 additions & 7 deletions src/modm/platform/timer/stm32/basic_base.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#ifndef MODM_STM32_TIMER_BASIC_BASE_HPP
#define MODM_STM32_TIMER_BASIC_BASE_HPP

#include <chrono>
#include <limits>
#include <stdint.h>
#include "../device.hpp"
#include <modm/architecture/interface/register.hpp>
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -101,6 +106,12 @@ public:
static inline void
setPrescaler(uint16_t prescaler);

/**
* Get current prescaler
*/
static inline uint16_t
getPrescaler();

/**
* Set overflow.
*
Expand All @@ -112,24 +123,31 @@ 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.
*
* @return New overflow value.
*
* @see applyAndReset()
*/
static uint16_t
setPeriod(uint32_t microseconds, bool autoApply = true);
template<class Rep, class Period>
static Value
setPeriod(std::chrono::duration<Rep, Period> duration, bool autoApply = true);

/**
* @brief Reset the counter, and update the prescaler and
Expand All @@ -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.
Expand Down

0 comments on commit 5ddcab3

Please sign in to comment.