24#include "boards/board_traits.h"
25#include <avr/interrupt.h>
51#define REGISTER_PULSE_TIMER8_AB_ISR(TIMER_NUM, PRESCALER, PIN_A, PIN_B) \
52 ISR(CAT3(TIMER, TIMER_NUM, _OVF_vect)) \
54 timer::isr_handler_pulse::pulse_timer_overflow<TIMER_NUM, PRESCALER, PIN_A, 0, PIN_B, 1>(); \
56 ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
58 timer::isr_handler_pulse::pulse_timer_compare<TIMER_NUM, 0, PIN_A>(); \
60 ISR(CAT3(TIMER, TIMER_NUM, _COMPB_vect)) \
62 timer::isr_handler_pulse::pulse_timer_compare<TIMER_NUM, 1, PIN_B>(); \
79#define REGISTER_PULSE_TIMER8_A_ISR(TIMER_NUM, PRESCALER, PIN_A) \
80 ISR(CAT3(TIMER, TIMER_NUM, _OVF_vect)) \
82 timer::isr_handler_pulse::pulse_timer_overflow<TIMER_NUM, PRESCALER, PIN_A, 0>(); \
84 ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
86 timer::isr_handler_pulse::pulse_timer_compare<TIMER_NUM, 0, PIN_A>(); \
88 EMPTY_INTERRUPT(CAT3(TIMER, TIMER_NUM, _COMPB_vect))
104#define REGISTER_PULSE_TIMER8_B_ISR(TIMER_NUM, PRESCALER, PIN_B) \
105 ISR(CAT3(TIMER, TIMER_NUM, _OVF_vect)) \
107 timer::isr_handler_pulse::pulse_timer_overflow<TIMER_NUM, PRESCALER, PIN_B, 1>(); \
109 ISR(CAT3(TIMER, TIMER_NUM, _COMPB_vect)) \
111 timer::isr_handler_pulse::pulse_timer_compare<TIMER_NUM, 1, PIN_B>(); \
113 EMPTY_INTERRUPT(CAT3(TIMER, TIMER_NUM, _COMPA_vect))
118 template<board::Timer NTIMER_, typename Calculator<NTIMER_>::PRESCALER PRESCALER_>
119 class PulseTimer16 :
public Timer<NTIMER_>
126 using TRAIT =
typename PARENT::TRAIT;
127 static_assert(TRAIT::IS_16BITS,
"TIMER must be a 16 bits timer");
131 using TPRESCALER =
typename CALCULATOR::PRESCALER;
132 static constexpr const TPRESCALER PRESCALER = PRESCALER_;
134 explicit PulseTimer16(uint16_t pulse_frequency) :
Timer<NTIMER>{TCCRA_MASK(), TCCRB_MASK()}
136 TRAIT::ICR = CALCULATOR::PWM_ICR_counter(PRESCALER, pulse_frequency);
140 static constexpr uint8_t TCCRA_MASK()
143 return TRAIT::F_PWM_ICR_TCCRA;
145 static constexpr uint8_t TCCRB_MASK()
148 return TRAIT::F_PWM_ICR_TCCRB | TRAIT::TCCRB_prescaler(PRESCALER);
152 template<board::Timer NTIMER_, typename Calculator<NTIMER_>::PRESCALER PRESCALER_>
153 class PulseTimer8 :
public Timer<NTIMER_>
160 using TRAIT =
typename PARENT::TRAIT;
161 static_assert(!TRAIT::IS_16BITS,
"TIMER must be an 8 bits timer");
165 using TPRESCALER =
typename CALCULATOR::PRESCALER;
166 static constexpr const TPRESCALER PRESCALER = PRESCALER_;
168 explicit PulseTimer8(uint16_t pulse_frequency)
169 :
Timer<NTIMER>{TCCRA_MASK(), TCCRB_MASK(), TIMSK_int_mask()}, MAX{OVERFLOW_COUNTER(pulse_frequency)}
179 if (count_ == MAX) count_ = 0;
180 return (count_ == 0);
183 static constexpr uint8_t TCCRA_MASK()
188 static constexpr uint8_t TCCRB_MASK()
191 return TRAIT::TCCRB_prescaler(PRESCALER);
193 static constexpr uint8_t TIMSK_int_mask()
195 return TRAIT::TIMSK_int_mask(uint8_t(TimerInterrupt::OVERFLOW | TimerInterrupt::OUTPUT_COMPARE_A
196 | TimerInterrupt::OUTPUT_COMPARE_B));
198 static constexpr uint8_t OVERFLOW_COUNTER(uint16_t pulse_frequency)
200 return F_CPU / TRAIT::MAX_COUNTER /
bits::BV16(uint8_t(PRESCALER)) / pulse_frequency;
206 friend struct isr_handler_pulse;
243 template<board::Timer NTIMER_, typename timer::Calculator<NTIMER_>::PRESCALER PRESCALER_,
244 typename T =
typename board_traits::Timer_trait<NTIMER_>::TYPE>
247 static_assert(types_traits::is_uint8_or_uint16<T>(),
"T must be either uint8_t or uint16_t");
259 template<board::Timer NTIMER_, typename timer::Calculator<NTIMER_>::PRESCALER PRESCALER_>
260 class PulseTimer<NTIMER_, PRESCALER_, uint8_t> :
public timer::PulseTimer8<NTIMER_, PRESCALER_>
263 explicit PulseTimer(uint16_t pulse_frequency) :
timer::PulseTimer8<NTIMER_, PRESCALER_>{pulse_frequency} {}
266 template<board::Timer NTIMER_, typename timer::Calculator<NTIMER_>::PRESCALER PRESCALER_>
267 class PulseTimer<NTIMER_, PRESCALER_, uint16_t> :
public timer::PulseTimer16<NTIMER_, PRESCALER_>
270 explicit PulseTimer(uint16_t pulse_frequency) :
timer::PulseTimer16<NTIMER_, PRESCALER_>{pulse_frequency} {}
276 struct isr_handler_pulse
278 template<u
int8_t TIMER_NUM_, board::PWMPin PIN_, u
int8_t COM_NUM_>
281 constexpr board::Timer NTIMER = isr_handler::check_timer<TIMER_NUM_>();
282 using TRAIT = board_traits::Timer_trait<NTIMER>;
283 static_assert(!TRAIT::IS_16BITS,
"TIMER_NUM must be an 8 bits Timer");
284 using PINT = board_traits::Timer_COM_trait<NTIMER, COM_NUM_>;
285 static_assert(PIN_ == PINT::PIN_OCR,
"PIN must be connected to TIMER_NUM OCxA/OCxB");
289 template<u
int8_t TIMER_NUM_,
typename timer::Calculator<(board::Timer) TIMER_NUM_>::PRESCALER PRESCALER_,
290 board::PWMPin PIN_, u
int8_t COM_NUM_>
291 static void pulse_timer_overflow()
293 static constexpr board::Timer NTIMER = pulse_timer_check<TIMER_NUM_, PIN_, COM_NUM_>();
294 using PT = timer::PulseTimer8<NTIMER, PRESCALER_>;
295 if (interrupt::HandlerHolder<PT>::handler()->overflow())
297 using PWMTRAIT = board_traits::PWMPin_trait<PIN_>;
302 template<u
int8_t TIMER_NUM_,
typename timer::Calculator<(board::Timer) TIMER_NUM_>::PRESCALER PRESCALER_,
303 board::PWMPin PINA_, u
int8_t COMA_NUM_, board::PWMPin PINB_, u
int8_t COMB_NUM_>
304 static void pulse_timer_overflow()
306 static constexpr board::Timer NTIMER = pulse_timer_check<TIMER_NUM_, PINA_, COMA_NUM_>();
307 pulse_timer_check<TIMER_NUM_, PINB_, COMB_NUM_>();
308 using PT = timer::PulseTimer8<NTIMER, PRESCALER_>;
309 if (interrupt::HandlerHolder<PT>::handler()->overflow())
311 using PINTA = board_traits::Timer_COM_trait<NTIMER, COMA_NUM_>;
312 using PINTB = board_traits::Timer_COM_trait<NTIMER, COMB_NUM_>;
315 using PWMTRAIT = board_traits::PWMPin_trait<PINA_>;
320 using PWMTRAIT = board_traits::PWMPin_trait<PINB_>;
326 template<u
int8_t TIMER_NUM_, u
int8_t COM_NUM_, board::PWMPin PIN_>
static void pulse_timer_compare()
328 static constexpr board::Timer NTIMER = pulse_timer_check<TIMER_NUM_, PIN_, COM_NUM_>();
329 using PINT = board_traits::Timer_COM_trait<NTIMER, COM_NUM_>;
330 static_assert(PIN_ == PINT::PIN_OCR,
"PIN must be connected to TIMER_NUM OCxA/OCxB");
331 using PWMTRAIT = board_traits::PWMPin_trait<PIN_>;
static void set()
Set pin level to HIGH (i.e.
static void clear()
Set pin level to LOW (i.e.
Special kind of timer::Timer, specialized in emitting pulses with accurate width, according to a slow...
PulseTimer(UNUSED uint16_t pulse_frequency)
Create a PulseTimer with the provided pulse_frequency.
General API to handle an AVR timer.
#define UNUSED
Specific GCC attribute to declare an argument or variable unused, so that the compiler does not emit ...
General Purpose (digital) Input Output API.
General API for handling AVR interrupt vectors.
static constexpr uint16_t BV16(uint8_t bit)
Create a uint16_t bitmask for the given bit number.
Timer
Defines all timers available for target MCU.
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
Defines all API to manipulate AVR Timers.
Defines a set of calculation methods for the given NTIMER_ The behavior of these methods is specific ...
Useful traits for common types.
General utilities API that have broad application in programs.