WebbotLib AVR library
WebbotLib It just does it
  C++ documentation  C documentation

timer.h

Defines Helper functions for the timers and compare channels.
Timers, in general, are probably the most complex subject when dealing with microprocessors and trying to create code which can port from one device to another especially with the added complexity of different cpu speeds. Timers have different modes: but each timer may only support some of those modes, and each timer may have several channels/pins that are linked to it.
This library attempts to de-mistify some of the above by providing a more intelligent API than other libraries.
Since your program must include a sys/*.h file then the library is aware of the AVR device you are using as well as the clock speed. The library also knows which timers are available for your selected device as well as the modes and channels that it supports.
Each timer has a name such as TIMER0, TIMER1, TIMER2 etc. Unlike other libraries we discourage you from reading values from any given timer in order to measure durations since the result is dependent on the clock speed and any prescaler. Instead we introduce the concept of an internal clock. This clock is not a 'time of day' clock in that it doesn't generate values that are guaranteed to increase. It will, after every 7 minutes, wrap around to zero but since I have never found a scenario where you need to measure incoming pulses any way near this value then it is not a problem. The clock is only defined after your 'app_init' code completes - at which time the library attempts to create the clock from any timers that are unused by your code. As a consequence none of the 'clock' functions will work during 'app_init' but the various 'delay' functions will.
I don't understand! What does that mean? Well in essence it means you should never ever do the following:-
uint32_t delay = timer0_get_overflow * 256 + TCNT0;
mainly because the result is linked to the CPU clock speed but is also 'full of bugs' caused by interrupts. Instead you should use the 'clock' functions in this library. So to measure how long something takes then:-
TICK_COUNT start = clockGetus();
...do something...
TICK_COUNT end = clockGetus();
TICK_COUNT duration = end - start;
Various general delay routines are also defined to allow you to create delays in cycles (not recommended), microseconds and milliseconds. Generally all delays are not a good idea as the processor just idles and the whole system just grinds to a halt - it will still work but you should consider rewriting your code so that other things continue to happen.
At the end of the day the 'beginner' doesn't need to worry about this file. There are higher level functions elsewhere to achieve given tasks. So if all of this is going 'over the top of your head' then don't worry - read on...

 

Function

 


TICK_COUNT clockGetus()

Get the current time in µS.
Note that this number will wrap around so a later reading may give a smaller value.
This happens every 0xffffffff or 4,294,967,295 microseconds ie every 4295 seconds or every 72 minutes (approx).
This means that the longest time difference you can sense by subtracting two values is about 72 minutes - this should not be a problem since if you are trying to do that then your program is probably wrong.
Note that, even with wrap around, you can always subtract two values to get a duration (so long as it's less than 72 minutes) ie:
TICK_COUNT start = clockGetus();
... do something ...
TICK_COUNT end = clockGetus();
TICK_COUNT duration = end - start; // the number of uS up to a maximum of 72 minutes
NB if this is called from app_init then it will have unknown results as the clock has not yet been created.

boolean clockHasElapsed(TICK_COUNT usStart, TICK_COUNT usWait)

Test if a given duration has elapsed.
Returns TRUE if it has or FALSE if not.
Whilst I wouldn't recommend doing this: here is an example that pauses for 10mS.
TICK_COUNT start = clockGetus(); // Get the start time
TICK_COUNT wait = 10000; // 10ms = 10000us
while(clockHasElapsed(start, wait)==FALSE){
    ... still waiting ...
}
NB if this is called from app_init then it will have unknown results as the clock has not yet been created.

boolean clockHasElapsedGetOverflow(TICK_COUNT usStart, TICK_COUNT usWait, TICK_COUNT* overflow)

Similar to 'clockHasElapsed' but returns the number of µS left to go if the duration has not elapsed, or the number of µS we have exceeded the duration if is has elapsed.
For example:
TICK_COUNT start = clockGetus();
TICK_COUNT wait = 10000; // wait for 10ms
TICK_COUNT overflow;
while(clockHasElapsedGetOverflow(start, wait, &overflow)==FALSE){
    // There are still 'overflow' µS left
}
// overflow has the number of µS in excess of 'wait' that we have actually waited for
NB if this is called from app_init then it will have unknown results as the clock has not yet been created.

clockWaitms(TICK_COUNT ms)

Pause for the given number of milliseconds.
So to wait for 1 second we could use:-
clockWaitms(1000);
NB The granularity of the clock is such that you should not assume that this waits for exactly 1 second- but rather that it waits for 'at least' one second.
NB if this is called from app_init then it will have unknown results as the clock has not yet been created.

clockWaitus(TICK_COUNT us)

Pause for the given number of microseconds.
So to wait for 100 microseconds we could use:-
clockWaitus(100);
NB The granularity of the clock is such that you should not assume that this waits for exactly 100 micro seconds- but rather that it waits for 'at least' that time.
NB if this is called from app_init then it will have unknown results as the clock has not yet been created.

delay_cycles(uint32_t __cycles)

Pause for the given number of clock cycles.
Note that the actual delay will vary depending upon the speed of the processor. In order to remove this dependency it is recommended that you use either the MS_TO_CYCLES or US_TO_CYCLES macro to convert an actual time into the number of clock cycles. For example: to delay by 100uS you should write:
delay_cycles(US_TO_CYCLES(100));
It is recommended that you use this function, rather than delay_ms or delay_us, if the delay is a fixed value and especially if the delay period is short. The reason being that the delay_ms and delay_us routines will first have to do some multiplications and divisions in order to convert the delay into cycles and the overhead of these calculations can sometimes take longer than the delay you require. Using the MS_TO_CYCLES and US_TO_CYCLES macros for a fixed delay means that the compiler will perform these calculations at compile time and thereby reduce the overhead at runtime.

delay_ms(uint32_t __ms)

Pause for the given number of ms.
This is similar to clockWaitms but will also work in app_init where the clock is not available.

delay_us(uint32_t __us)

Pause for the given number of µs.
This is similar to clockWaitus but will also work in app_init where the clock is not available.

uint32_t ticks_per_ms(uint32_t ms, uint16_t prescale)

Returns the number of timer ticks that would be generated for the given number of milliseconds if the timer used the given prescaler.
This is normally used in conjunction with timerGetBestPrescaler(const Timer* timer, uint16_t repeat_ms). You would use timerGetBestPrescaler(const Timer* timer, uint16_t repeat_ms) to find the optimum prescaler value for the timer and then use this value in ticks_per_ms(uint32_t ms, uint16_t prescale) to find the number of ticks that would be generated for the given number of ms.

uint64_t MS_TO_CYCLES(ms)

Convert milliseconds into a number of cycles.
Because the cpu speed is only known when building an end-user program then this macro is not available if you are writing a new library function.
Also see: delay_ms, delay_cycles

uint64_t US_TO_CYCLES(us)

Convert microseconds into a number of cycles.
Because the cpu speed is only known when building an end-user program then this macro is not available if you are writing a new library function.
Also see: delay_us, delay_cycles

timerOverflowAttach(const Timer* timer, TimerCallback callback, void* user_data )

Register an overflow callback.
This registers a function that is called every time this timer overflows from TOP to BOTTOM. The final parameter is an optional pointer to some user defined data. The library doesn't chage this data, it is purely there for your own use and may be 'null' if there is none.
Each timer can only have one registered overflow callback routine at a time. If you need to change the callback (unlikely?) then you should use timerOverflowDetach(const Timer* timer) to remove any existing callback prior to calling this routine.

timerOverflowDetach(const Timer* timer)

Remove any overflow callback for the given timer.

timerOverflowClearInterruptPending(const Timer* timer)

Clears the timers 'overflow interrupt pending' flag.
Normally only required when reconfiguring a timer so don't use it unless you understand what this means!

boolean timerOverflowIsInterruptPending(const Timer* timer)

Test if an overflow interrupt is pending for the given timer.
It only makes sense to call this when interrupts are disabled or in an interrupt service routine as, if we are in the foreground, then the interrupt will trigger and we will never be able to test for it. This routine will return TRUE if an overflow interrupt is pending and will be triggered when interrupts are re-enabled.

boolean timerIsCaptureSupported(const Timer* timer)

Returns TRUE if this timer supports Input Capture.

timerCaptureAttach(const Timer* timer, TimerCallback callback, void* user_data, boolean risingEdge )

Register a capture callback.
This registers a function that is called every time the capture input pin for this timer goes low->high (if last parameter is TRUE) or high->low (if last parameter is FALSE) . The third parameter is an optional pointer to some user defined data. The library doesn't chage this data, it is purely there for your own use and may be 'null' if there is none.
Each timer can only have one registered capture callback routine at a time. If you need to change the callback (unlikely?) then you should use timerCaptureDetach(const Timer* timer) to remove any existing callback prior to calling this routine.

timerCaptureDetach(const Timer* timer)

Remove any capture callback for the given timer.

timerCaptureClearInterruptPending(const Timer* timer)

Clears the timers 'capture interrupt pending' flag.
Normally only required when reconfiguring a timer so don't use it unless you understand what this means!

boolean timerCaptureIsInterruptPending(const Timer* timer)

Test if a capture interrupt is pending for the given timer.
It only makes sense to call this when interrupts are disabled or in an interrupt service routine as, if we are in the foreground, then the interrupt will trigger and we will never be able to test for it. This routine will return TRUE if a capture interrupt is pending and will be triggered when interrupts are re-enabled.

const IOPin* timerGetCapturePin(const Timer* timer)

Returns the IOPin used for input capture.
If the timer does not support input capture mode, or the IOPin is not available on your system, then this will return null.

boolean timerSupportsCompare(const Timer* timer)

Does the timer have any compare units?
Return TRUE if the timer has at least one compare unit.

uint8_t timerNumberOfCompareUnits(const Timer* timer)

Returns the number of compare units provided by this timer.
Typically this will return a number between 0 and 3.

const TimerCompare* timerGetCompare(const Timer* timer, uint8_t channel)

Find the compare unit for a given timer.
Each timer typically has between 0 and 3 compare units.
The first parameter specifies the timer (eg TIMER0, TIMER1 etc) and the second parameter is the compare unit number from 0 up to 'timerNumberOfCompareUnits(const Timer* timer) - 1'.

TIMER_MODE timerGetMode(const Timer*timer)

Returns the current mode for a timer.
The modes are:
TIMER_MODE_NORMAL,
TIMER_MODE_PWM8_PHASE_CORRECT,
TIMER_MODE_PWM9_PHASE_CORRECT,
TIMER_MODE_PWM10_PHASE_CORRECT,
TIMER_MODE_CTC_OCR,
TIMER_MODE_PWM8_FAST,
TIMER_MODE_PWM9_FAST,
TIMER_MODE_PWM10_FAST,
TIMER_MODE_PWM_PHASE_FREQ_ICR,
TIMER_MODE_PWM_PHASE_FREQ_OCR,
TIMER_MODE_PWM_PHASE_CORRECT_ICR,
TIMER_MODE_PWM_PHASE_CORRECT_OCR,
TIMER_MODE_CTC_ICR,
TIMER_MODE_13_RESVD,
TIMER_MODE_PWM_FAST_ICR,
TIMER_MODE_PWM_FAST_OCR

timerSetMode(const Timer* timer, TIMER_MODE mode)

Set the operating mode for the given timer.
Only use this if you know that the timer is not currently in use ie 'timerIsInUse' returns FALSE. For a list of possible modes see timerGetMode(const Timer*timer)

boolean  timerIsModeSupported(const Timer* timer, TIMER_MODE mode)

Test if a timer supports a given mode of operation.
Some timers support all modes whilst others only support a subset of the possible modes.

uint16_t timerGetBestPrescaler(const Timer* timer, uint16_t repeat_ms)

Find the optimum prescaler value for the given timer in order to measure the given number of ms.
This function takes into account the different prescale options for the given timer and whether it is a 16 bit or 8 bit timer and will return the smallest prescale value capable of measuring the given delay taking into account the clock speed of the microprocessor.
This will return a value such as 1, 16, 64, 128 etc.

boolean  timerSupportsPrescaler(const Timer* timer, uint16_t prescaler)

Does the timer support the given prescaler value?

uint16_t timerGetCounter(const Timer* timer)

Returns the current counter value for the timer.
This always returns a 16 bit value but for an 8 bit timer the top byte will always be 0x00. This function should not be used to calculate durations as the actual timings will vary according to clock speeds, prescalers etc and there are other more friendly methods to this. It's main use is in other library functions when setting compare thresholds - see uartsw.c for an example.

uint16_t timerGetPrescaler(const Timer* timer)

Returns the current clock prescaler value for this timer.

timerSetPrescaler(const Timer* timer, uint16_t prescaler)

Set the clock prescaler value for the given timer.

uint16_t timerGetTOP(const Timer* timer)

Returns the current value of TOP for the given timer.
This is used by library routines such as the motor drivers in order to calculate the required compare unit value for a given duty cycle.

boolean timerIsInUse(const Timer* timer)

Test if a given timer is currently in use.

timerOff(const Timer* timer)

Tuen off the specified timer.
Use this with extreme caution! If you have used 'timerIsInUse' to locate an unused timer, and then return it to the timer pool via this call then all is ok. But don't suddenly turn off another timer at random since it may be used for motor control or for the clock.

boolean timerIs16bit(const Timer* timer)

Is the given timer a 16 bit timer?
Return TRUE if it is a 16 bit timer, or FALSE if it is an 8 bit timer.

compareAttach(const TimerCompare* channel, TimerCompareCallback callback, uint16_t threshold, void* data )

Attach a callback function to a compare unit.
Only one callback function can be registered per compare unit at a time - see compateDetach.
The callback function is called once the timer value reaches the threshold value. Note that if this value is greater than the value of TOP (as returned by timerGetTOP(const Timer* timer) ) then this will never happen and the callback will never be called.
The first parameter specifies which compare unit.
The second parameter is the address of your function that will be called. This function should have the following signature:
void myCallBack(const TimerCompare *timer_compare, void* data);
If you don't want a function to be called then use: &nullTimerCompareCallback
The third parameter specifies the value used to trigger the compare match.
The last parameter is for your own use and is often used to pass a reference to some data that needs to be passed into your callback function.

compareDetach(const TimerCompare* compare)

Removes any callback function from the given compare unit.

compareClearInterruptPending(const TimerCompare* channel)

Clears the 'interrupt pending' flag for the compare unit.
This is normally only used when interrupts are switched off for example when initialising the timer.

boolean compareIsInterruptPending(const TimerCompare* channel)

Test if the compare unit has set the 'interrupt pending' flag.
This is only of use when interrupts are turned off - otherwise the interrupt happens and the flag is cleared. So if this function returns TRUE then it means that as soon as interrupts are re-enabled then the callback routine will be called.

const TimerCompare* compareFromIOPin(const IOPin* pin)

Find the compare unit that can be used to toggle the specified IOPin.
Compare units can be used purely for timing purposes but more often they are used to output waveforms (such as PWM) on a given pin. Each compare unit is therefore associated with a given IO pin. This function allows you to locate the compare unit for a given IOPin. It will return 'null' if there is no compare unit associated.
Note that on some devices the same pin is used by more than one timer. In this case priority is given to the 16 bit timer.
For example on an Axon then calling: compareFromIOPin(H4) will return Timer 4 Channel B. However calling: compareFromIOPin(B7) should return Timer 0 Channel A but since this has no header pin on the Axon then it will return 'null'.

const IOPin* compareGetPin(const TimerCompare* channel)

Returns the IOPin associated with a given compare unit or null if there isn't one or it has no header pin on this board.
Also see:compareFromIOPin(const IOPin* pin) for the reverse action

uint16_t compareGetThreshold(const TimerCompare* channel)

Returns the threshold value for the given compare unit.

compareSetThreshold(const TimerCompare* channel, uint16_t threshold)

Changes the threshold value for the compare unit.

const Timer* compareGetTimer(const TimerCompare* compare)

Returns the Timer that this compare unit is associated with.

boolean compareIsInUse(const TimerCompare* channel)

Tests if a given compare unit is currently in use.
This is useful if you want to use a compare unit for timing purposes rather than generating a waveform on an IOPin. You can iterate through all the timers and compare units to locate one that is not currently in use.

CHANNEL_MODE compareGetOutputMode(const TimerCompare* channel)

Find the mode used for toggling the PWM output pin of a compare channel when the compare threshold is met.
This will return one of the following values:
CHANNEL_MODE_DISCONNECT - if the output pin is left unchanged
CHANNEL_MODE_TOGGLE - if the output pin is toggled
CHANNEL_MODE_NON_INVERTING - if the output pin is set low
CHANNEL_MODE_INVERTING - if the output pin is set high

compareSetOutputMode(const TimerCompare* channel, CHANNEL_MODE mode)

Sets the output mode of the compare unit.
The following modes are supported:
CHANNEL_MODE_DISCONNECT,
CHANNEL_MODE_TOGGLE,
CHANNEL_MODE_NON_INVERTING,
CHANNEL_MODE_INVERTING

uint8_t NUMBER_OF_TIMERS

A constant value representing the number of Timers in the microprocessor.
This can be used to iterate through the list of timers as follows:-
for(int8_t t=0; t<NUMBER_OF_TIMERS-1; t++){
const Timer * timer = &pgm_Timers[t];
}

Valid XHTML 1.0 Transitional