Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[platform:timer] support std::chrono in Timer**::setPeriod #873

Merged
merged 2 commits into from
Jun 13, 2022
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
19 changes: 10 additions & 9 deletions examples/blue_pill_f103/encoder_input_bitbang/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ MODM_ISR(TIM2)
encoder.update();
}

template<class Timer, class Rep, class Period>
void
init_Timer2(const uint16_t period)
initPeriodicInterrupt(std::chrono::duration<Rep, Period> period)
{
Timer2::enable();
Timer2::setMode(Timer2::Mode::UpCounter);
Timer::enable();
Timer::setMode(Timer::Mode::UpCounter);

Timer2::template setPeriod<Board::SystemClock>(period);
Timer2::enableInterruptVector(true, 10);
Timer2::enableInterrupt(Timer2::Interrupt::Update);
Timer::template setPeriod<Board::SystemClock>(period);
Timer::enableInterruptVector(true, 10);
Timer::enableInterrupt(Timer::Interrupt::Update);

Timer2::applyAndReset();
Timer2::start();
Timer::applyAndReset();
Timer::start();
}

int
Expand All @@ -61,7 +62,7 @@ main()
Usart2::initialize<Board::SystemClock, 115200_Bd>();

encoder.initialize();
init_Timer2(1000); // 1ms period
initPeriodicInterrupt<Timer2>(1ms);

int value(0);

Expand Down
2 changes: 1 addition & 1 deletion examples/nucleo_f042k6/vector_table_ram/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ main()

Timer14::enable();
Timer14::setMode(Timer14::Mode::UpCounter);
Timer14::setPeriod<Board::SystemClock>(500'000 /* us */);
Timer14::setPeriod<Board::SystemClock>(500ms);
Timer14::applyAndReset();
Timer14::start();
Timer14::enableInterrupt(Timer14::Interrupt::Update);
Expand Down
2 changes: 1 addition & 1 deletion examples/nucleo_l031k6/vector_table_ram/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ main()

Timer2::enable();
Timer2::setMode(Timer2::Mode::UpCounter);
Timer2::setPeriod<Board::SystemClock>(500'000 /* us */);
Timer2::setPeriod<Board::SystemClock>(500ms);
Timer2::applyAndReset();
Timer2::start();
Timer2::enableInterrupt(Timer2::Interrupt::Update);
Expand Down
2 changes: 1 addition & 1 deletion examples/stm32f3_discovery/timer/basic/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ main()
//Timer1::setMode(Timer1::Mode::CenterAligned3);
Timer1::setMode(Timer1::Mode::UpCounter);
Timer1::setOverflow(0xff);
//Timer1::setPeriod(4);
//Timer1::setPeriod(4us);
Timer1::applyAndReset();
Timer1::start();

Expand Down
4 changes: 2 additions & 2 deletions examples/stm32f4_discovery/timer_test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ testTimerAdvancedStart()
TIMER::enable();
TIMER::setMode(TIMER::Mode::UpCounter);

TIMER::template setPeriod<Board::SystemClock>(250000);
TIMER::template setPeriod<Board::SystemClock>(250ms);
TIMER::enableInterruptVector(TIMER::Interrupt::Update, true, 10);
TIMER::enableInterrupt(TIMER::Interrupt::Update);

Expand All @@ -54,7 +54,7 @@ testTimerStart()
TIMER::enable();
TIMER::setMode(TIMER::Mode::UpCounter);

TIMER::template setPeriod<Board::SystemClock>(250000);
TIMER::template setPeriod<Board::SystemClock>(250ms);
TIMER::enableInterruptVector(true, 10);
TIMER::enableInterrupt(TIMER::Interrupt::Update);

Expand Down
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>
TomSaw marked this conversation as resolved.
Show resolved Hide resolved
[[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
Loading