Sound Byte Libs 1ee2ca6
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
interval_timer.hpp
Go to the documentation of this file.
1#ifndef SBL_CORE_PATTERNS_TIMING_INTERVAL_TIMER_HPP_
2#define SBL_CORE_PATTERNS_TIMING_INTERVAL_TIMER_HPP_
3
4/**
5 * @file interval_timer.hpp
6 * @brief Generic interrupt-driven interval timing for precise events
7 * @ingroup patterns
8 *
9 * Provides generic interval timing using hardware timer interrupts.
10 * No domain-specific logic - just precise microsecond interval generation.
11 * Applications handle their own domain logic (BPM, frequencies, etc).
12 */
13
14#include <sbl/hal/hardware_timer.hpp>
16
17namespace sbl {
18namespace core {
19namespace patterns {
20namespace timing {
21
22/**
23 * @brief Generic interrupt-driven interval timer
24 *
25 * Provides precise interval timing using hardware timer interrupts.
26 * No musical or domain-specific logic - just generic interval generation.
27 * Applications convert their domain values (BPM, frequencies) to microseconds.
28 *
29 * Usage:
30 * 1. Construct with timer instance
31 * 2. Set interval in microseconds and start()
32 * 3. Poll hasTriggered() in main loop
33 * 4. Interrupt handling is automatic via registry
34 *
35 * @tparam TimerImpl Hardware timer implementation
36 */
37template<typename TimerImpl>
39public:
40 /**
41 * @brief Construct interval timer
42 * @param timer_instance Hardware timer instance to use
43 */
44 explicit IntervalTimer(uint32_t timer_instance)
45 : timerInstance_(timer_instance), intervalMicros_(1000000), // Default 1Hz
46 running_(false), triggered_(false) {
47
48 // Initialize hardware timer
49 sbl::core::hal::HardwareTimer<TimerImpl>::initialize(timerInstance_);
50 }
51
52 /**
53 * @brief Set interval in microseconds
54 * @param interval_us Interval duration in microseconds
55 *
56 * Generic timing - no domain-specific logic.
57 * Applications convert their values to microseconds:
58 * - Audio: sample_rate -> (1,000,000 / sample_rate) us
59 * - BPM: bpm -> (60,000,000 / bpm) us
60 * - Hz: freq -> (1,000,000 / freq) us
61 */
62 void setIntervalMicros(uint32_t interval_us) {
63 intervalMicros_ = interval_us;
64
65 if (running_) {
66 // Reconfigure timer immediately if already running
67 sbl::core::hal::HardwareTimer<TimerImpl>::configure(
68 timerInstance_, intervalMicros_, sbl::core::hal::TimerMode::Periodic);
69 }
70 }
71
72 /**
73 * @brief Get current interval in microseconds
74 * @return Current interval duration
75 */
76 uint32_t getIntervalMicros() const {
77 return intervalMicros_;
78 }
79
80 /**
81 * @brief Start the interval timer
82 */
83 void start() {
84 if (!running_) {
85 using HwTimer = sbl::core::hal::HardwareTimer<TimerImpl>;
86 using TimerRegistry = sbl::core::hal::TimerInterruptRegistry<>;
87
88 // Configure timer for periodic interrupts
89 HwTimer::configure(timerInstance_, intervalMicros_,
90 sbl::core::hal::TimerMode::Periodic);
91
92 // Register static interrupt handler
93 registerInstance(timerInstance_, this);
94 TimerRegistry::registerHandler(timerInstance_,
95 sbl::core::hal::TimerInterrupt::Update,
96 &IntervalTimer::staticInterruptHandler);
97
98 // Enable interrupt and start timer
99 HwTimer::enableInterrupt(timerInstance_,
100 sbl::core::hal::TimerInterrupt::Update,
101 sbl::core::hal::InterruptPriority::High);
102
103 HwTimer::reset(timerInstance_);
104 HwTimer::start(timerInstance_);
105
106 running_ = true;
107 triggered_ = false;
108 }
109 }
110
111 /**
112 * @brief Stop the interval timer
113 */
114 void stop() {
115 if (running_) {
116 using HwTimer = sbl::core::hal::HardwareTimer<TimerImpl>;
117 using TimerRegistry = sbl::core::hal::TimerInterruptRegistry<>;
118
119 HwTimer::stop(timerInstance_);
120 HwTimer::disableInterrupt(timerInstance_,
121 sbl::core::hal::TimerInterrupt::Update);
122
123 // Unregister handler
124 TimerRegistry::unregisterHandler(timerInstance_,
125 sbl::core::hal::TimerInterrupt::Update);
126 unregisterInstance(timerInstance_);
127
128 running_ = false;
129 triggered_ = false;
130 }
131 }
132
133 /**
134 * @brief Check if timer is running
135 * @return true if running, false if stopped
136 */
137 bool isRunning() const {
138 return running_ && sbl::core::hal::HardwareTimer<TimerImpl>::isRunning(timerInstance_);
139 }
140
141 /**
142 * @brief Check if interval has triggered
143 * @return true if interval occurred since last check
144 *
145 * This is a one-shot check - returns true once per trigger.
146 * Call from main loop for event handling.
147 */
149 if (triggered_) {
150 triggered_ = false; // Clear flag after reading
151 return true;
152 }
153 return false;
154 }
155
156 /**
157 * @brief Timer interrupt handler - call from ISR
158 *
159 * Called automatically via interrupt registry.
160 * Just sets internal flag - no callbacks or complex logic in ISR.
161 */
163 triggered_ = true;
164 }
165
166private:
167 // Static interrupt handler for registry
168 static void staticInterruptHandler() {
169 // Find which timer instance triggered and call its handler
170 // This is a simplified approach - in production you'd get the
171 // timer instance from the interrupt vector
172 for (uint8_t i = 0; i < 8; ++i) {
173 if (instances_[i] &&
174 sbl::core::hal::HardwareTimer<TimerImpl>::isInterruptPending(
175 i, sbl::core::hal::TimerInterrupt::Update)) {
176
177 // Clear interrupt flag
178 sbl::core::hal::HardwareTimer<TimerImpl>::clearInterrupt(
179 i, sbl::core::hal::TimerInterrupt::Update);
180
181 // Call instance handler
182 instances_[i]->handleTimerInterrupt();
183 }
184 }
185 }
186
187 // Static instance registry for interrupt handling
188 static void registerInstance(uint32_t timer_instance, IntervalTimer* instance) {
189 if (timer_instance < 8) { // Max 8 timer instances
190 instances_[timer_instance] = instance;
191 }
192 }
193
194 static void unregisterInstance(uint32_t timer_instance) {
195 if (timer_instance < 8) {
196 instances_[timer_instance] = nullptr;
197 }
198 }
199
200 static IntervalTimer* instances_[8]; // Static instance registry
201
202 uint32_t timerInstance_;
203 uint32_t intervalMicros_;
204 bool running_;
205 volatile bool triggered_; // Volatile for ISR/main loop communication
206};
207
208} // namespace timing
209} // namespace patterns
210} // namespace core
211} // namespace sbl
212
213// Static member definitions
214template<typename TimerImpl>
215IntervalTimer<TimerImpl>* IntervalTimer<TimerImpl>::instances_[8] = {};
216
217#endif // SBL_CORE_PATTERNS_TIMING_INTERVAL_TIMER_HPP_
Generic interrupt-driven interval timer.
IntervalTimer(uint32_t timer_instance)
Construct interval timer.
void start()
Start the interval timer.
bool hasTriggered()
Check if interval has triggered.
void setIntervalMicros(uint32_t interval_us)
Set interval in microseconds.
uint32_t getIntervalMicros() const
Get current interval in microseconds.
bool isRunning() const
Check if timer is running.
void handleTimerInterrupt()
Timer interrupt handler - call from ISR.
Integer math utilities for embedded systems.
Root namespace for all Sound Byte Libs functionality.
Definition aliases.hpp:24