v1.0.0
[hackover2013-badge-firmware.git] / core / timer16 / timer16.c
1 /**************************************************************************/
2 /*!
3 @file timer16.c
4 @author K. Townsend (microBuilder.eu)
5
6 @section DESCRIPTION
7
8 Generic code for both 16-bit timers.
9
10 @warning 16-bit timers are limited to roughly ~0.91ms (or 910uS) on
11 a system running at 72MHz since:
12 @code
13 1 mS = CFG_CPU_CCLK / 1000
14 = 72000000 / 1000
15 = 72000 'ticks'
16 @endcode
17 Meaning that 0xFFFF (65535) 'ticks' = 0.910208 milliseconds
18 or 910 microseconds.
19
20 @section Example
21
22 @code
23 #include "/core/cpu/cpu.h"
24 #include "/core/timer16/timer16.h"
25
26 // Instantiated in timer16.h
27 extern volatile uint32_t timer16_0_counter;
28 ...
29 cpuInit();
30
31 // Initialise timer0 with a delay of 0xFFFF, which will cause the
32 // timer interrupt to fire every 65535 ticks and increment
33 // timer16_0_counter by 1
34 timer16Init(0, 0xFFFF);
35
36 // Enable the timer
37 timer16Enable(0);
38
39 // At this point timer16_0_counter should start incrementing by 1
40 // every 65535 ticks
41 @endcode
42
43 @section LICENSE
44
45 Software License Agreement (BSD License)
46
47 Copyright (c) 2010, microBuilder SARL
48 All rights reserved.
49
50 Redistribution and use in source and binary forms, with or without
51 modification, are permitted provided that the following conditions are met:
52 1. Redistributions of source code must retain the above copyright
53 notice, this list of conditions and the following disclaimer.
54 2. Redistributions in binary form must reproduce the above copyright
55 notice, this list of conditions and the following disclaimer in the
56 documentation and/or other materials provided with the distribution.
57 3. Neither the name of the copyright holders nor the
58 names of its contributors may be used to endorse or promote products
59 derived from this software without specific prior written permission.
60
61 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
62 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
65 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
66 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
67 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
68 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
69 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
70 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 */
72 /**************************************************************************/
73
74 #include "timer16.h"
75
76 volatile uint32_t timer16_0_counter = 0;
77 volatile uint32_t timer16_1_counter = 0;
78
79 #ifdef CFG_PWM
80 volatile uint32_t pwmCounter = 0;
81 extern volatile uint32_t pwmMaxPulses; // See drivers/pwm/pwm.c
82 #endif
83
84 /**************************************************************************/
85 /*!
86 @brief Causes a blocking delay for the specified number of
87 clock ticks.
88
89 @note The exact duration of this delay depends on the speed of the
90 system clock, but it will invariably be short because of the
91 16-bit limitation. For example, on a system with a 72MHz
92 clock, a 1mS delay would be equal to 72,000 ticks, which is
93 already above the maximum 16-bit value of 65,535. Thus, the
94 maximum delay measured in mS with a 72MHz clock is ~0.91mS.
95
96 @param[in] timerNum
97 The 16-bit timer to user (0..1)
98 @param[in] delayInTicks
99 The number of clock ticks to delay (0..65534)
100
101 @section Example
102
103 @code
104 #include "/core/cpu/cpu.h"
105 #include "/core/timer16/timer16.h"
106
107 int main(void)
108 {
109 cpuInit();
110
111 // Initialise timer 0 ... delay is provided but not used here
112 timer16Init(0, 0xFFFF);
113
114 // Enable the timer
115 timer16Enable(0);
116
117 while(1)
118 {
119 // Cause blocking delay for 36000 ticks (0.5mS @ 72MHz)
120 // Note: The delay must be 65534 or less (16-bit value)
121 timer16DelayTicks(0, 36000);
122 }
123 }
124 @endcode
125 */
126 /**************************************************************************/
127 void timer16DelayTicks(uint8_t timerNum, uint16_t delayInTicks)
128 {
129 // ToDo: Verify incoming value
130
131 if (timerNum == 0)
132 {
133 /* Reset the timer */
134 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
135
136 /* Set the prescaler to zero */
137 TMR_TMR16B0PR = 0x00;
138
139 TMR_TMR16B0MR0 = delayInTicks;
140
141 /* Reset all interrupts */
142 TMR_TMR16B0IR = TMR_TMR16B0IR_MASK_ALL;
143
144 /* Stop timer on match (MR0) */
145 TMR_TMR16B0MCR = TMR_TMR16B0MCR_MR0_STOP_ENABLED;
146
147 /* Start timer */
148 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
149
150 /* Wait until the delay time has elapsed */
151 while (TMR_TMR16B0TCR & TMR_TMR16B0TCR_COUNTERENABLE_ENABLED);
152 }
153
154 else if (timerNum == 1)
155 {
156 /* Reset the timer */
157 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
158
159 /* Set the prescaler to zero */
160 TMR_TMR16B1PR = 0x00;
161
162 TMR_TMR16B1MR0 = delayInTicks;
163
164 /* Reset all interrupts */
165 TMR_TMR16B1IR = TMR_TMR16B1IR_MASK_ALL;
166
167 /* Stop timer on match (MR0) */
168 TMR_TMR16B1MCR = TMR_TMR16B1MCR_MR0_STOP_ENABLED;
169
170 /* Start timer */
171 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
172
173 /* Wait until the delay time has elapsed */
174 while (TMR_TMR16B1TCR & TMR_TMR16B1TCR_COUNTERENABLE_ENABLED);
175 }
176
177 return;
178 }
179
180 /**************************************************************************/
181 /*!
182 @brief Causes a blocking delay for the specified number of
183 microseconds
184
185 @warning The maximum delay in uS will depend on the clock speed,
186 but running at 72MHz the maximum delay (MR = 0xFFFF)
187 would be 910uS (0xFFFF / 72 = 910), or 0.91 milliseconds.
188
189 @param[in] timerNum
190 The 16-bit timer to user (0..1)
191 @param[in] delayInUs
192 The number of microseconds to wait
193
194 @section Example
195
196 @code
197 #include "/core/cpu/cpu.h"
198 #include "/core/timer16/timer16.h"
199
200 int main(void)
201 {
202 cpuInit();
203
204 // Initialise timer 0 ... delay is provided but not used here
205 timer16Init(0, 0xFFFF);
206
207 // Enable the timer
208 timer16Enable(0);
209
210 while(1)
211 {
212 // Cause blocking delay for 500 microseconds (0.5mS)
213 timer16DelayUS(0, 500);
214 }
215 }
216 @endcode
217 */
218 /**************************************************************************/
219 void timer16DelayUS(uint8_t timerNum, uint16_t delayInUS)
220 {
221 // ToDo: Check if the appropriate timer is enabled first?
222
223 if (timerNum == 0)
224 {
225 /* Reset the timer */
226 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
227
228 /* Set the prescaler to zero */
229 TMR_TMR16B0PR = 0x00;
230
231 TMR_TMR16B0MR0 = delayInUS * ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV)/1000000);
232
233 /* Reset all interrupts */
234 TMR_TMR16B0IR = TMR_TMR16B0IR_MASK_ALL;
235
236 /* Stop timer on match (MR0) */
237 TMR_TMR16B0MCR = TMR_TMR16B0MCR_MR0_STOP_ENABLED;
238
239 /* Start timer */
240 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
241
242 /* Wait until the delay time has elapsed */
243 while (TMR_TMR16B0TCR & TMR_TMR16B0TCR_COUNTERENABLE_ENABLED);
244 }
245
246 else if (timerNum == 1)
247 {
248 /* Reset the timer */
249 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
250
251 /* Set the prescaler to zero */
252 TMR_TMR16B1PR = 0x00;
253
254 TMR_TMR16B1MR0 = delayInUS * ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV)/1000000);
255
256 /* Reset all interrupts */
257 TMR_TMR16B1IR = TMR_TMR16B1IR_MASK_ALL;
258
259 /* Stop timer on match (MR0) */
260 TMR_TMR16B1MCR = TMR_TMR16B1MCR_MR0_STOP_ENABLED;
261
262 /* Start timer */
263 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
264
265 /* Wait until the delay time has elapsed */
266 while (TMR_TMR16B1TCR & TMR_TMR16B1TCR_COUNTERENABLE_ENABLED);
267 }
268
269 return;
270 }
271
272 /**************************************************************************/
273 /*!
274 @brief Interrupt handler for 16-bit timer 0
275 */
276 /**************************************************************************/
277 void TIMER16_0_IRQHandler(void)
278 {
279 /* Clear the interrupt flag */
280 TMR_TMR16B0IR = TMR_TMR16B0IR_MR0;
281
282 /* Increment timer counter by 1 (it will automatically roll back to 0) */
283 timer16_0_counter++;
284 return;
285 }
286
287 /**************************************************************************/
288 /*!
289 @brief Interrupt handler for 16-bit timer 1
290 */
291 /**************************************************************************/
292 void TIMER16_1_IRQHandler(void)
293 {
294 /* Clear the interrupt flag */
295 TMR_TMR16B1IR = TMR_TMR16B1IR_MR0;
296
297 /* Increment timer counter by 1 (it will automatically roll back to 0) */
298 timer16_1_counter++;
299
300 #ifdef CFG_PWM
301 /* Check if the PWM output should be disabled after pwmMaxPulses pulses */
302 /* See "drivers/pwm/pwm.c" */
303 if (TMR_TMR16B1IR & TMR_TMR16B1IR_MR3)
304 {
305 /* Clear the interrupt flag */
306 TMR_TMR16B1IR = TMR_TMR16B1IR_MR3;
307
308 if (pwmMaxPulses > 0)
309 {
310 pwmCounter++;
311 if (pwmCounter == pwmMaxPulses)
312 {
313 /* Disable interrupt on MR3 */
314 TMR_TMR16B1MCR &= ~(TMR_TMR16B1MCR_MR3_INT_MASK);
315 /* Disable Timer */
316 TMR_TMR16B1TCR &= ~(TMR_TMR16B1TCR_COUNTERENABLE_MASK);
317 /* Reset the counter variables */
318 pwmCounter = 0;
319 pwmMaxPulses = 0;
320 }
321 }
322 }
323 #endif
324
325 return;
326 }
327
328 /**************************************************************************/
329 /*!
330 @brief Enables the specified timer
331
332 @param[in] timerNum
333 The 16-bit timer to enable (0..1)
334 */
335 /**************************************************************************/
336 void timer16Enable(uint8_t timerNum)
337 {
338 if ( timerNum == 0 )
339 {
340 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
341 }
342
343 else if (timerNum == 1)
344 {
345 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
346 }
347
348 return;
349 }
350
351 /**************************************************************************/
352 /*!
353 @brief Disables the specified timer
354
355 @param[in] timerNum
356 The 16-bit timer to disable (0..1)
357 */
358 /**************************************************************************/
359 void timer16Disable(uint8_t timerNum)
360 {
361 if ( timerNum == 0 )
362 {
363 TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_DISABLED;
364 }
365
366 else if (timerNum == 1)
367 {
368 TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_DISABLED;
369 }
370
371 return;
372 }
373
374 /**************************************************************************/
375 /*!
376 @brief Resets the specified timer
377
378 @param[in] timerNum
379 The 16-bit timer to reset (0..1)
380 */
381 /**************************************************************************/
382 void timer16Reset(uint8_t timerNum)
383 {
384 uint32_t regVal;
385
386 if ( timerNum == 0 )
387 {
388 regVal = TMR_TMR16B0TCR;
389 regVal |= TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
390 TMR_TMR16B0TCR = regVal;
391 }
392
393 else if (timerNum == 1)
394 {
395 regVal = TMR_TMR16B1TCR;
396 regVal |= TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
397 TMR_TMR16B1TCR = regVal;
398 }
399
400 return;
401 }
402
403 /**************************************************************************/
404 /*!
405 @brief Initialises the specified 16-bit timer, sets the timer
406 interval, resets the timer, and configures the interrupt
407 handler.
408
409 Initialises a 16-bit timer with the supplied timer interval (the
410 amount of time that passes between each timer 'tick'). Every time that
411 this interval elapses, the timer's interrupt will be fired and the
412 appropriate counter variable will be incremented by one (For example,
413 with CT16B0, 'timer16_0_counter' would be incremented).
414
415 @param[in] timerNum
416 The 16-bit timer to initiliase (0..1)
417 @param[in] timerInterval
418 The number of clock 'ticks' between resets (0..65534)
419
420 @warning Care needs to be taken when configuring the timers since
421 the pins are all multiplexed with other peripherals. This
422 code is provided as a starting point, but it will need to
423 be adjusted according to your own situation and
424 pin/peripheral requirements
425 */
426 /**************************************************************************/
427 void timer16Init(uint8_t timerNum, uint16_t timerInterval)
428 {
429 // If timerInterval is invalid, use the default value
430 if (timerInterval < 1)
431 {
432 timerInterval = TIMER16_DEFAULTINTERVAL;
433 }
434
435 if ( timerNum == 0 )
436 {
437 /* Enable the clock for CT16B0 */
438 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B0);
439
440 /* The physical pins associated with CT16B0 are not enabled by
441 default in order to avoid conflicts with other peripherals.
442 Pin 0.10 (CT16B0_MAT2), for example, can not be used while
443 debugging with a hardware debugger. If you require one or
444 more of these pins, simply uncomment the code below */
445
446 /* Configure PIO0.2 as Timer0_16 CAP0 */
447 // IOCON_PIO0_2 &= ~IOCON_PIO0_2_FUNC_MASK;
448 // IOCON_PIO0_2 |= IOCON_PIO0_2_FUNC_CT16B0_CAP0;
449
450 /* Configure PIO0.8 as Timer0_16 MAT0 */
451 // IOCON_PIO0_8 &= ~IOCON_PIO0_8_FUNC_MASK;
452 // IOCON_PIO0_8 |= IOCON_PIO0_8_FUNC_CT16B0_MAT0;
453
454 /* Configure PIO0.9 as Timer0_16 MAT1 */
455 // IOCON_PIO0_9 &= ~IOCON_PIO0_9_FUNC_MASK;
456 // IOCON_PIO0_9 |= IOCON_PIO0_9_FUNC_CT16B0_MAT1;
457
458 /* Configure PIO0.10 as Timer0_16 MAT3 */
459 // IOCON_JTAG_TCK_PIO0_10 &= ~IOCON_JTAG_TCK_PIO0_10_FUNC_MASK;
460 // IOCON_JTAG_TCK_PIO0_10 |= IOCON_JTAG_TCK_PIO0_10_FUNC_CT16B0_MAT2;
461
462 timer16_0_counter = 0;
463 TMR_TMR16B0MR0 = timerInterval;
464
465 /* Configure match control register to raise an interrupt and reset on MR0 */
466 TMR_TMR16B0MCR = (TMR_TMR16B0MCR_MR0_INT_ENABLED | TMR_TMR16B0MCR_MR0_RESET_ENABLED);
467
468 /* Enable the TIMER0 interrupt */
469 NVIC_EnableIRQ(TIMER_16_0_IRQn);
470 }
471
472 else if ( timerNum == 1 )
473 {
474 /* Enable the clock for CT16B1 */
475 SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B1);
476
477 /* The physical pins associated with CT16B0 are not enabled by
478 default in order to avoid conflicts with other peripherals.
479 Pin 0.10 (CT16B0_MAT2), for example, can not be used while
480 debugging with a hardware debugger. If you require one or
481 more of these pins, simply uncomment the code below */
482
483 /* Configure PIO1.8 as Timer1_16 CAP0 */
484 // IOCON_PIO1_8 &= ~IOCON_PIO1_8_FUNC_MASK;
485 // IOCON_PIO1_8 |= IOCON_PIO1_8_FUNC_CT16B1_CAP0;
486
487 /* Configure PIO1.9 as Timer1_16 MAT0 */
488 // IOCON_PIO1_9 &= ~IOCON_PIO1_9_FUNC_MASK;
489 // IOCON_PIO1_9 |= IOCON_PIO1_9_FUNC_CT16B1_MAT0;
490
491 /* Configure PIO1.10 as Timer1_16 MAT1 */
492 // IOCON_PIO1_10 &= ~IOCON_PIO1_10_FUNC_MASK;
493 // IOCON_PIO1_10 |= IOCON_PIO1_10_FUNC_CT16B1_MAT1;
494
495 timer16_1_counter = 0;
496 TMR_TMR16B1MR0 = timerInterval;
497
498 /* Configure match control register to raise an interrupt and reset on MR0 */
499 TMR_TMR16B1MCR = (TMR_TMR16B1MCR_MR0_INT_ENABLED | TMR_TMR16B1MCR_MR0_RESET_ENABLED);
500
501 /* Enable the TIMER1 Interrupt */
502 NVIC_EnableIRQ(TIMER_16_1_IRQn);
503 }
504 return;
505 }
This page took 0.069616 seconds and 5 git commands to generate.