1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
8 Generic code for both 16-bit timers.
10 @warning 16-bit timers are limited to roughly ~0.91ms (or 910uS) on
11 a system running at 72MHz since:
13 1 mS = CFG_CPU_CCLK / 1000
17 Meaning that 0xFFFF (65535) 'ticks' = 0.910208 milliseconds
23 #include "/core/cpu/cpu.h"
24 #include "/core/timer16/timer16.h"
26 // Instantiated in timer16.h
27 extern volatile uint32_t timer16_0_counter;
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);
39 // At this point timer16_0_counter should start incrementing by 1
45 Software License Agreement (BSD License)
47 Copyright (c) 2010, microBuilder SARL
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.
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.
72 /**************************************************************************/
76 volatile uint32_t timer16_0_counter
= 0;
77 volatile uint32_t timer16_1_counter
= 0;
80 volatile uint32_t pwmCounter
= 0;
81 extern volatile uint32_t pwmMaxPulses
; // See drivers/pwm/pwm.c
84 /**************************************************************************/
86 @brief Causes a blocking delay for the specified number of
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.
97 The 16-bit timer to user (0..1)
98 @param[in] delayInTicks
99 The number of clock ticks to delay (0..65534)
104 #include "/core/cpu/cpu.h"
105 #include "/core/timer16/timer16.h"
111 // Initialise timer 0 ... delay is provided but not used here
112 timer16Init(0, 0xFFFF);
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);
126 /**************************************************************************/
127 void timer16DelayTicks(uint8_t timerNum
, uint16_t delayInTicks
)
129 // ToDo: Verify incoming value
133 /* Reset the timer */
134 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERRESET_ENABLED
;
136 /* Set the prescaler to zero */
137 TMR_TMR16B0PR
= 0x00;
139 TMR_TMR16B0MR0
= delayInTicks
;
141 /* Reset all interrupts */
142 TMR_TMR16B0IR
= TMR_TMR16B0IR_MASK_ALL
;
144 /* Stop timer on match (MR0) */
145 TMR_TMR16B0MCR
= TMR_TMR16B0MCR_MR0_STOP_ENABLED
;
148 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERENABLE_ENABLED
;
150 /* Wait until the delay time has elapsed */
151 while (TMR_TMR16B0TCR
& TMR_TMR16B0TCR_COUNTERENABLE_ENABLED
);
154 else if (timerNum
== 1)
156 /* Reset the timer */
157 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERRESET_ENABLED
;
159 /* Set the prescaler to zero */
160 TMR_TMR16B1PR
= 0x00;
162 TMR_TMR16B1MR0
= delayInTicks
;
164 /* Reset all interrupts */
165 TMR_TMR16B1IR
= TMR_TMR16B1IR_MASK_ALL
;
167 /* Stop timer on match (MR0) */
168 TMR_TMR16B1MCR
= TMR_TMR16B1MCR_MR0_STOP_ENABLED
;
171 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERENABLE_ENABLED
;
173 /* Wait until the delay time has elapsed */
174 while (TMR_TMR16B1TCR
& TMR_TMR16B1TCR_COUNTERENABLE_ENABLED
);
180 /**************************************************************************/
182 @brief Causes a blocking delay for the specified number of
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.
190 The 16-bit timer to user (0..1)
192 The number of microseconds to wait
197 #include "/core/cpu/cpu.h"
198 #include "/core/timer16/timer16.h"
204 // Initialise timer 0 ... delay is provided but not used here
205 timer16Init(0, 0xFFFF);
212 // Cause blocking delay for 500 microseconds (0.5mS)
213 timer16DelayUS(0, 500);
218 /**************************************************************************/
219 void timer16DelayUS(uint8_t timerNum
, uint16_t delayInUS
)
221 // ToDo: Check if the appropriate timer is enabled first?
225 /* Reset the timer */
226 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERRESET_ENABLED
;
228 /* Set the prescaler to zero */
229 TMR_TMR16B0PR
= 0x00;
231 TMR_TMR16B0MR0
= delayInUS
* ((CFG_CPU_CCLK
/SCB_SYSAHBCLKDIV
)/1000000);
233 /* Reset all interrupts */
234 TMR_TMR16B0IR
= TMR_TMR16B0IR_MASK_ALL
;
236 /* Stop timer on match (MR0) */
237 TMR_TMR16B0MCR
= TMR_TMR16B0MCR_MR0_STOP_ENABLED
;
240 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERENABLE_ENABLED
;
242 /* Wait until the delay time has elapsed */
243 while (TMR_TMR16B0TCR
& TMR_TMR16B0TCR_COUNTERENABLE_ENABLED
);
246 else if (timerNum
== 1)
248 /* Reset the timer */
249 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERRESET_ENABLED
;
251 /* Set the prescaler to zero */
252 TMR_TMR16B1PR
= 0x00;
254 TMR_TMR16B1MR0
= delayInUS
* ((CFG_CPU_CCLK
/SCB_SYSAHBCLKDIV
)/1000000);
256 /* Reset all interrupts */
257 TMR_TMR16B1IR
= TMR_TMR16B1IR_MASK_ALL
;
259 /* Stop timer on match (MR0) */
260 TMR_TMR16B1MCR
= TMR_TMR16B1MCR_MR0_STOP_ENABLED
;
263 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERENABLE_ENABLED
;
265 /* Wait until the delay time has elapsed */
266 while (TMR_TMR16B1TCR
& TMR_TMR16B1TCR_COUNTERENABLE_ENABLED
);
272 /**************************************************************************/
274 @brief Interrupt handler for 16-bit timer 0
276 /**************************************************************************/
277 void TIMER16_0_IRQHandler(void)
279 /* Clear the interrupt flag */
280 TMR_TMR16B0IR
= TMR_TMR16B0IR_MR0
;
282 /* Increment timer counter by 1 (it will automatically roll back to 0) */
287 /**************************************************************************/
289 @brief Interrupt handler for 16-bit timer 1
291 /**************************************************************************/
292 void TIMER16_1_IRQHandler(void)
294 /* Clear the interrupt flag */
295 TMR_TMR16B1IR
= TMR_TMR16B1IR_MR0
;
297 /* Increment timer counter by 1 (it will automatically roll back to 0) */
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
)
305 /* Clear the interrupt flag */
306 TMR_TMR16B1IR
= TMR_TMR16B1IR_MR3
;
308 if (pwmMaxPulses
> 0)
311 if (pwmCounter
== pwmMaxPulses
)
313 /* Disable interrupt on MR3 */
314 TMR_TMR16B1MCR
&= ~(TMR_TMR16B1MCR_MR3_INT_MASK
);
316 TMR_TMR16B1TCR
&= ~(TMR_TMR16B1TCR_COUNTERENABLE_MASK
);
317 /* Reset the counter variables */
328 /**************************************************************************/
330 @brief Enables the specified timer
333 The 16-bit timer to enable (0..1)
335 /**************************************************************************/
336 void timer16Enable(uint8_t timerNum
)
340 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERENABLE_ENABLED
;
343 else if (timerNum
== 1)
345 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERENABLE_ENABLED
;
351 /**************************************************************************/
353 @brief Disables the specified timer
356 The 16-bit timer to disable (0..1)
358 /**************************************************************************/
359 void timer16Disable(uint8_t timerNum
)
363 TMR_TMR16B0TCR
= TMR_TMR16B0TCR_COUNTERENABLE_DISABLED
;
366 else if (timerNum
== 1)
368 TMR_TMR16B1TCR
= TMR_TMR16B1TCR_COUNTERENABLE_DISABLED
;
374 /**************************************************************************/
376 @brief Resets the specified timer
379 The 16-bit timer to reset (0..1)
381 /**************************************************************************/
382 void timer16Reset(uint8_t timerNum
)
388 regVal
= TMR_TMR16B0TCR
;
389 regVal
|= TMR_TMR16B0TCR_COUNTERRESET_ENABLED
;
390 TMR_TMR16B0TCR
= regVal
;
393 else if (timerNum
== 1)
395 regVal
= TMR_TMR16B1TCR
;
396 regVal
|= TMR_TMR16B1TCR_COUNTERRESET_ENABLED
;
397 TMR_TMR16B1TCR
= regVal
;
403 /**************************************************************************/
405 @brief Initialises the specified 16-bit timer, sets the timer
406 interval, resets the timer, and configures the interrupt
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).
416 The 16-bit timer to initiliase (0..1)
417 @param[in] timerInterval
418 The number of clock 'ticks' between resets (0..65534)
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
426 /**************************************************************************/
427 void timer16Init(uint8_t timerNum
, uint16_t timerInterval
)
429 // If timerInterval is invalid, use the default value
430 if (timerInterval
< 1)
432 timerInterval
= TIMER16_DEFAULTINTERVAL
;
437 /* Enable the clock for CT16B0 */
438 SCB_SYSAHBCLKCTRL
|= (SCB_SYSAHBCLKCTRL_CT16B0
);
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 */
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;
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;
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;
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;
462 timer16_0_counter
= 0;
463 TMR_TMR16B0MR0
= timerInterval
;
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
);
468 /* Enable the TIMER0 interrupt */
469 NVIC_EnableIRQ(TIMER_16_0_IRQn
);
472 else if ( timerNum
== 1 )
474 /* Enable the clock for CT16B1 */
475 SCB_SYSAHBCLKCTRL
|= (SCB_SYSAHBCLKCTRL_CT16B1
);
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 */
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;
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;
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;
495 timer16_1_counter
= 0;
496 TMR_TMR16B1MR0
= timerInterval
;
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
);
501 /* Enable the TIMER1 Interrupt */
502 NVIC_EnableIRQ(TIMER_16_1_IRQn
);