Commit 28682b5923ba5095e2bcf52b8c65d0dd5c725712

Authored by Antonio Carlos Domínguez Brito
1 parent b08d202b
Exists in master

Changes:

1. Added versions of functions is_stopped(), is_unset() and is_overrun() without arguments.

2. Functions get_duty_and_period() and get_duty_period_and_pulses() is order to avoid restarting if desired.

These changes have been carried out thanks to the comments and suggestions of Github's user balinthanula.
Showing 1 changed file with 274 additions and 247 deletions   Show diff stats
tc_lib.h
... ... @@ -120,262 +120,289 @@ namespace arduino_due
120 120 {
121 121 public:
122 122  
123   - static constexpr const uint32_t DEFAULT_MAX_OVERRUNS=100;
  123 + static constexpr const uint32_t DEFAULT_MAX_OVERRUNS=100;
124 124  
125   - capture() {}
  125 + capture() {}
126 126  
127   - ~capture() {}
  127 + ~capture() {}
128 128  
129 129 capture(const capture&) = delete;
130   - capture(capture&&) = delete;
131   - capture& operator=(const capture&) = delete;
132   - capture& operator=(capture&&) = delete;
133   -
134   - static void tc_interrupt(uint32_t the_status)
135   - { _ctx_.tc_interrupt(the_status); }
136   -
137   - // NOTE: the_capture_window parameter in config() refers to
138   - // the time window for measuring the duty of a PWM signal. As
139   - // a rule of thumb if the PWM signal you want to measure has
140   - // a period T, the capture window should be at least twice this
141   - // time, that is, 2T. Parameter the_overruns specify how many
142   - // loading overruns are tolerated before ceasing capturing.
143   - bool config(
144   - uint32_t the_capture_window,
145   - uint32_t the_overruns = DEFAULT_MAX_OVERRUNS
146   - ) { return _ctx_.config(the_capture_window,the_overruns); }
147   -
148   - constexpr uint32_t ticks_per_usec() { return _ctx_.ticks_per_usec(); }
149   - constexpr uint32_t max_capture_window() { return _ctx_.max_capture_window(); }
150   -
151   - // NOTE: member function get_duty_and_period() returns
152   - // the status of the capture object. Returns in arguments
153   - // the last valid measured and period.
154   - uint32_t get_duty_and_period(
155   - uint32_t& the_duty,
156   - uint32_t& the_period
157   - )
158   - { return _ctx_.get_duty_and_period(the_duty,the_period); }
159   -
160   - // NOTE: member function get_duty_and_period() returns
161   - // the status of the capture object. Returns in arguments
162   - // the last valid measured and period, and the count of
163   - // pulses accumulated since the last config.
164   - uint32_t get_duty_period_and_pulses(
165   - uint32_t& the_duty,
166   - uint32_t& the_period,
167   - uint32_t& the_pulses
168   - )
169   - {
170   - return _ctx_.get_duty_period_and_pulses(
171   - the_duty,
172   - the_period,
173   - the_pulses
174   - );
175   - }
176   -
177   - uint32_t get_capture_window() { return _ctx_.capture_window; }
178   -
179   - bool is_overrun(uint32_t the_status)
180   - { return _ctx_.is_overrun(the_status); }
181   -
182   - // NOTE: when too much loading overruns have been detected
183   - // the capture stops measuring to avoid the use of compu-
184   - // tational resources. Take into account that if the sig-
185   - // nal measured has a frequency around 1 Mhz or higher the
186   - // interrupts due to the capture object will consume all
187   - // CPU time. If this is the case, the capture object stops
188   - // capturing when the overun threshold is surpassed.
189   - bool is_stopped(uint32_t the_status)
190   - { return _ctx_.is_stopped(the_status); }
191   -
192   - // NOTE:capture object is unset when not configured
193   - bool is_unset(uint32_t the_status)
194   - { return _ctx_.is_unset(the_status); }
195   -
196   - void stop() { _ctx_.stop(); }
197   - void restart() { _ctx_.restart(); }
198   -
199   - void lock()
200   - {
201   - if( is_unset() || is_stopped() ) return;
202   - timer::disable_interrupts();
203   - }
204   -
205   - void unlock()
206   - {
207   - if( is_unset() || is_stopped() ) return;
208   - timer::enable_interrupts();
209   - }
  130 + capture(capture&&) = delete;
  131 + capture& operator=(const capture&) = delete;
  132 + capture& operator=(capture&&) = delete;
  133 +
  134 + static void tc_interrupt(uint32_t the_status)
  135 + { _ctx_.tc_interrupt(the_status); }
  136 +
  137 + // NOTE: the_capture_window parameter in config() refers to
  138 + // the time window for measuring the duty of a PWM signal. As
  139 + // a rule of thumb if the PWM signal you want to measure has
  140 + // a period T, the capture window should be at least twice this
  141 + // time, that is, 2T. Parameter the_overruns specify how many
  142 + // loading overruns are tolerated before ceasing capturing.
  143 + bool config(
  144 + uint32_t the_capture_window,
  145 + uint32_t the_overruns = DEFAULT_MAX_OVERRUNS
  146 + ) { return _ctx_.config(the_capture_window,the_overruns); }
  147 +
  148 + constexpr uint32_t ticks_per_usec() { return _ctx_.ticks_per_usec(); }
  149 + constexpr uint32_t max_capture_window() { return _ctx_.max_capture_window(); }
  150 +
  151 + // NOTE: member function get_duty_and_period() returns
  152 + // the status of the capture object. Returns in arguments
  153 + // the last valid measured and period. By default, the
  154 + // capture object get restarted when stopped, setting
  155 + // do_restart to false avoid restarting
  156 + uint32_t get_duty_and_period(
  157 + uint32_t& the_duty,
  158 + uint32_t& the_period,
  159 + bool do_restart = true
  160 + )
  161 + { return _ctx_.get_duty_and_period(
  162 + the_duty,
  163 + the_period,
  164 + do_restart);
  165 + }
  166 +
  167 + // NOTE: member function get_duty_and_period() returns
  168 + // the status of the capture object. Returns in arguments
  169 + // the last valid measured and period, and the count of
  170 + // pulses accumulated since the last config. By default, the
  171 + // capture object get restarted when stopped, setting
  172 + // do_restart to false avoid restarting
  173 +
  174 + uint32_t get_duty_period_and_pulses(
  175 + uint32_t& the_duty,
  176 + uint32_t& the_period,
  177 + uint32_t& the_pulses,
  178 + bool do_restart = true
  179 + )
  180 + {
  181 + return _ctx_.get_duty_period_and_pulses(
  182 + the_duty,
  183 + the_period,
  184 + the_pulses,
  185 + do_restart
  186 + );
  187 + }
  188 +
  189 + uint32_t get_capture_window() { return _ctx_.capture_window; }
  190 +
  191 + bool is_overrun() { return _ctx_.is_overrun(); }
  192 +
  193 + bool is_overrun(uint32_t the_status)
  194 + { return _ctx_.is_overrun(the_status); }
  195 +
  196 + // NOTE: when too much loading overruns have been detected
  197 + // the capture stops measuring to avoid the use of compu-
  198 + // tational resources. Take into account that if the sig-
  199 + // nal measured has a frequency around 1 Mhz or higher the
  200 + // interrupts due to the capture object will consume all
  201 + // CPU time. If this is the case, the capture object stops
  202 + // capturing when the overun threshold is surpassed.
  203 + bool is_stopped() { return _ctx_.is_stopped(); }
  204 +
  205 + bool is_stopped(uint32_t the_status)
  206 + { return _ctx_.is_stopped(the_status); }
  207 +
  208 + // NOTE:capture object is unset when not configured
  209 + bool is_unset() { return _ctx_.is_unset(); }
  210 +
  211 + bool is_unset(uint32_t the_status)
  212 + { return _ctx_.is_unset(the_status); }
  213 +
  214 + void stop() { _ctx_.stop(); }
  215 + void restart() { _ctx_.restart(); }
  216 +
  217 + void lock()
  218 + {
  219 + if( is_unset() || is_stopped() ) return;
  220 + timer::disable_interrupts();
  221 + }
  222 +
  223 + void unlock()
  224 + {
  225 + if( is_unset() || is_stopped() ) return;
  226 + timer::enable_interrupts();
  227 + }
210 228  
211 229 private:
212 230  
213   - using timer = tc_core<TIMER>;
  231 + using timer = tc_core<TIMER>;
214 232  
215 233 struct _capture_ctx_
216   - {
217   - enum status_codes: uint32_t
218   - {
219   - UNSET=0,
220   - SET=1,
221   - OVERRUN=2,
222   - STOPPED=4
223   - };
224   -
225   - _capture_ctx_() {}
226   -
227   - bool config(uint32_t the_capture_window, uint32_t the_overruns);
228   -
229   - void tc_interrupt(uint32_t the_status);
230   -
231   - static constexpr uint32_t ticks_per_usec()
232   - {
233   - // NOTE: we will be using the fastest clock for TC ticks
234   - // just using a prescaler of 2
235   - return
236   - static_cast<uint32_t>( ((VARIANT_MCK)>>1)/1000000 );
237   - }
238   -
239   - static constexpr uint32_t max_capture_window()
240   - {
241   - return
242   - static_cast<uint32_t>(
243   - (static_cast<long long>(1)<<32)-static_cast<long long>(1)
244   - ) / ticks_per_usec();
245   - }
246   -
247   - uint32_t get_duty_and_period(
248   - uint32_t& the_duty,
249   - uint32_t& the_period
250   - )
251   - {
252   - uint32_t the_status=status;
253   - if(is_unset(the_status)) return the_status;
254   -
255   - timer::disable_interrupts();
256   - the_duty=duty; the_period=period;
257   - the_status=status;
258   - status=status&(~status_codes::OVERRUN);
259   - timer::enable_interrupts();
260   -
261   - if(is_stopped(the_status)) restart();
262   -
263   - return the_status;
264   - }
265   -
266   - uint32_t get_duty_period_and_pulses(
267   - uint32_t& the_duty,
268   - uint32_t& the_period,
269   - uint32_t& the_pulses
270   - )
271   - {
272   - uint32_t the_status=status;
273   - if(is_unset(the_status)) return the_status;
274   -
275   - timer::disable_interrupts();
276   - the_duty=duty; the_period=period; the_pulses=pulses;
277   - the_status=status;
278   - status=status&(~status_codes::OVERRUN);
279   - timer::enable_interrupts();
280   -
281   - if(is_stopped(the_status)) restart();
282   -
283   - return the_status;
284   - }
285   -
286   - bool is_overrun(uint32_t the_status)
287   - { return (the_status&status_codes::OVERRUN); }
288   -
289   - bool is_stopped(uint32_t the_status)
290   - { return (the_status&status_codes::STOPPED); }
291   -
292   - bool is_unset(uint32_t the_status)
293   - { return !the_status; }
294   -
295   - void stop()
296   - {
297   - uint32_t the_status=status;
298   - if(
299   - is_unset(the_status) ||
300   - is_stopped(the_status)
301   - ) return;
302   -
303   - timer::stop_interrupts();
304   - status=status|status_codes::STOPPED;
305   - }
306   -
307   - void restart()
308   - {
309   - uint32_t the_status=status;
310   - if(
311   - is_unset(the_status) ||
312   - !is_stopped(the_status)
313   - ) return;
314   -
315   - ra=duty=period=overruns=0;
316   - status&=
317   - ~(status_codes::OVERRUN|status_codes::STOPPED);
318   -
319   - // clearing pending interrupt flags
320   - uint32_t dummy=TC_GetStatus(
321   - timer::info::tc_p,
322   - timer::info::channel
323   - );
324   - timer::start_interrupts();
325   - }
326   -
327   - void end()
328   - {
329   - uint32_t the_status=status;
330   - if(is_unset(the_status)) return;
331   -
332   - timer::stop_interrupts();
333   - timer::disable_lovr_interrupt();
334   - timer::disable_ldra_interrupt();
335   - timer::disable_ldrb_interrupt();
336   - timer::disable_rc_interrupt();
337   - pmc_disable_periph_clk(uint32_t(timer::info::irq));
338   -
339   - status=status_codes::UNSET;
340   - }
341   -
342   - void load_overrun()
343   - {
344   - status=status|status_codes::OVERRUN;
345   - if((++overruns)>max_overruns)
346   - {
347   - timer::stop_interrupts();
348   - status=status|status_codes::STOPPED;
349   - }
350   - }
351   -
352   - void ra_loaded()
353   - {
354   - ra=timer::info::tc_p->TC_CHANNEL[timer::info::channel].TC_RA;
355   - }
356   -
357   - void rb_loaded()
358   - {
359   - period=timer::info::tc_p->TC_CHANNEL[timer::info::channel].TC_RB;
360   - duty=period-ra; pulses++;
361   - }
362   -
363   - void rc_matched() { ra=duty=period=0; }
364   -
365   - // capture values
366   - volatile uint32_t ra;
367   - volatile uint32_t duty;
368   - volatile uint32_t period;
369   - volatile uint32_t pulses;
370   - volatile uint32_t overruns;
371   - volatile uint32_t status;
372   -
373   - uint32_t rc;
374   - uint32_t capture_window;
375   - uint32_t max_overruns;
376   - };
377   -
378   - static _capture_ctx_ _ctx_;
  234 + {
  235 + enum status_codes: uint32_t
  236 + {
  237 + UNSET=0,
  238 + SET=1,
  239 + OVERRUN=2,
  240 + STOPPED=4
  241 + };
  242 +
  243 + _capture_ctx_() {}
  244 +
  245 + bool config(uint32_t the_capture_window, uint32_t the_overruns);
  246 +
  247 + void tc_interrupt(uint32_t the_status);
  248 +
  249 + static constexpr uint32_t ticks_per_usec()
  250 + {
  251 + // NOTE: we will be using the fastest clock for TC ticks
  252 + // just using a prescaler of 2
  253 + return
  254 + static_cast<uint32_t>( ((VARIANT_MCK)>>1)/1000000 );
  255 + }
  256 +
  257 + static constexpr uint32_t max_capture_window()
  258 + {
  259 + return
  260 + static_cast<uint32_t>(
  261 + (static_cast<long long>(1)<<32)-static_cast<long long>(1)
  262 + ) / ticks_per_usec();
  263 + }
  264 +
  265 + uint32_t get_duty_and_period(
  266 + uint32_t& the_duty,
  267 + uint32_t& the_period,
  268 + bool do_restart
  269 + )
  270 + {
  271 + uint32_t the_status=status;
  272 + if(is_unset(the_status)) return the_status;
  273 +
  274 + timer::disable_interrupts();
  275 + the_duty=duty; the_period=period;
  276 + the_status=status;
  277 + status=status&(~status_codes::OVERRUN);
  278 + timer::enable_interrupts();
  279 +
  280 + if(is_stopped(the_status) && do_restart) restart();
  281 +
  282 + return the_status;
  283 + }
  284 +
  285 + uint32_t get_duty_period_and_pulses(
  286 + uint32_t& the_duty,
  287 + uint32_t& the_period,
  288 + uint32_t& the_pulses,
  289 + bool do_restart
  290 + )
  291 + {
  292 + uint32_t the_status=status;
  293 + if(is_unset(the_status)) return the_status;
  294 +
  295 + timer::disable_interrupts();
  296 + the_duty=duty; the_period=period; the_pulses=pulses;
  297 + the_status=status;
  298 + status=status&(~status_codes::OVERRUN);
  299 + timer::enable_interrupts();
  300 +
  301 + if(is_stopped(the_status) && do_restart) restart();
  302 +
  303 + return the_status;
  304 + }
  305 +
  306 + bool is_overrun()
  307 + { return (status&status_codes::OVERRUN); }
  308 +
  309 + bool is_overrun(uint32_t the_status)
  310 + { return (the_status&status_codes::OVERRUN); }
  311 +
  312 + bool is_stopped()
  313 + { return (status&status_codes::STOPPED); }
  314 +
  315 + bool is_stopped(uint32_t the_status)
  316 + { return (the_status&status_codes::STOPPED); }
  317 +
  318 + bool is_unset() { return !status; }
  319 +
  320 + bool is_unset(uint32_t the_status) { return !the_status; }
  321 +
  322 + void stop()
  323 + {
  324 + uint32_t the_status=status;
  325 + if(
  326 + is_unset(the_status) ||
  327 + is_stopped(the_status)
  328 + ) return;
  329 +
  330 + timer::stop_interrupts();
  331 + status=status|status_codes::STOPPED;
  332 + }
  333 +
  334 + void restart()
  335 + {
  336 + uint32_t the_status=status;
  337 + if(
  338 + is_unset(the_status) ||
  339 + !is_stopped(the_status)
  340 + ) return;
  341 +
  342 + ra=duty=period=overruns=0;
  343 + status&=
  344 + ~(status_codes::OVERRUN|status_codes::STOPPED);
  345 +
  346 + // clearing pending interrupt flags
  347 + uint32_t dummy=TC_GetStatus(
  348 + timer::info::tc_p,
  349 + timer::info::channel
  350 + );
  351 + timer::start_interrupts();
  352 + }
  353 +
  354 + void end()
  355 + {
  356 + uint32_t the_status=status;
  357 + if(is_unset(the_status)) return;
  358 +
  359 + timer::stop_interrupts();
  360 + timer::disable_lovr_interrupt();
  361 + timer::disable_ldra_interrupt();
  362 + timer::disable_ldrb_interrupt();
  363 + timer::disable_rc_interrupt();
  364 + pmc_disable_periph_clk(uint32_t(timer::info::irq));
  365 +
  366 + status=status_codes::UNSET;
  367 + }
  368 +
  369 + void load_overrun()
  370 + {
  371 + status=status|status_codes::OVERRUN;
  372 + if((++overruns)>max_overruns)
  373 + {
  374 + timer::stop_interrupts();
  375 + status=status|status_codes::STOPPED;
  376 + }
  377 + }
  378 +
  379 + void ra_loaded()
  380 + {
  381 + ra=timer::info::tc_p->TC_CHANNEL[timer::info::channel].TC_RA;
  382 + }
  383 +
  384 + void rb_loaded()
  385 + {
  386 + period=timer::info::tc_p->TC_CHANNEL[timer::info::channel].TC_RB;
  387 + duty=period-ra; pulses++;
  388 + }
  389 +
  390 + void rc_matched() { ra=duty=period=0; }
  391 +
  392 + // capture values
  393 + volatile uint32_t ra;
  394 + volatile uint32_t duty;
  395 + volatile uint32_t period;
  396 + volatile uint32_t pulses;
  397 + volatile uint32_t overruns;
  398 + volatile uint32_t status;
  399 +
  400 + uint32_t rc;
  401 + uint32_t capture_window;
  402 + uint32_t max_overruns;
  403 + };
  404 +
  405 + static _capture_ctx_ _ctx_;
379 406 };
380 407  
381 408 template<timer_ids TIMER>
... ...