You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.8 KiB
94 lines
2.8 KiB
/** @file delay.h
|
|
@author M. P. Hayes, UCECE
|
|
@date 08 June 2002
|
|
@brief Delay routines for timing.
|
|
@note All files that use DELAY_US must be compiled with full optimisation.
|
|
|
|
@defgroup delay Delay routines
|
|
|
|
This module provides routines for short timing delays. These are
|
|
implemented as delay loops. DELAY_US must not be called with a variable
|
|
argument since the run-time floating point calculation will almost certainly
|
|
swamp the delay you require.
|
|
|
|
@note The macro F_CPU defines the CPU clock frequency (in Hertz).
|
|
*/
|
|
#ifndef DELAY_H
|
|
#define DELAY_H
|
|
|
|
#include "system.h"
|
|
#include <util/delay.h>
|
|
|
|
/* There are two timing loop routines provided in delay.h:
|
|
|
|
_delay_loop_1 uses an 8-bit counter and requires 3 cycles per
|
|
iteration but has a maximum of 256 iterations. With F_CPU = 8e6
|
|
then the range of delays is 0.375 us to 96.0 us in steps of 0.375 us.
|
|
|
|
_delay_loop_2 uses a 16-bit counter, requires 4 cycles per
|
|
iteration and has a maximum of 65536 iterations. With F_CPU = 8e6
|
|
then the range of delays is 0.5 us to 32.768 ms in steps of 0.5 us. */
|
|
|
|
#define DELAY1_LOOP_CYCLES 3
|
|
#define DELAY1_LOOPS_MAX 256
|
|
#define DELAY1_US_MAX (DELAY1_LOOPS_MAX * DELAY1_LOOP_CYCLES * 1e6 / (F_CPU))
|
|
|
|
#define DELAY2_LOOP_CYCLES 4
|
|
#define DELAY2_LOOPS_MAX 65536
|
|
#define DELAY2_US_MAX (DELAY2_LOOPS_MAX * DELAY2_LOOP_CYCLES * 1e6 / (F_CPU))
|
|
|
|
|
|
/** Delay a selected number of microseconds
|
|
@param us number of microseconds to delay. This must be a constant.
|
|
@note This should be only used with a constant argument otherwise
|
|
it will expand to a lot of code and require slow floating point operations to compute
|
|
the number of cycles to delay. */
|
|
#define DELAY_US(us) \
|
|
do \
|
|
{ \
|
|
if ((us) > DELAY1_US_MAX) \
|
|
{ \
|
|
double __tmp2 = ((double)F_CPU * (us)) / (DELAY2_LOOP_CYCLES * 1e6); \
|
|
uint16_t __ticks2; \
|
|
\
|
|
if ((us) > DELAY2_US_MAX) \
|
|
__ticks2 = 0; \
|
|
else \
|
|
__ticks2 = (uint16_t)__tmp2; \
|
|
_delay_loop_2 (__ticks2); \
|
|
} \
|
|
else \
|
|
{ \
|
|
double __tmp1 = ((double)F_CPU * (us)) / (DELAY1_LOOP_CYCLES * 1e6); \
|
|
uint8_t __ticks1; \
|
|
\
|
|
if (__tmp1 < 1.0) \
|
|
__ticks1 = 1; \
|
|
else \
|
|
__ticks1 = (uint8_t)__tmp1; \
|
|
_delay_loop_1 (__ticks1); \
|
|
} \
|
|
} \
|
|
while (0)
|
|
|
|
|
|
/** Delay a selected number of milliseconds
|
|
@param ms number of milliseconds to delay. This can be a variable. */
|
|
static __inline__ void
|
|
delay_ms (uint8_t ms)
|
|
{
|
|
/* FIXME: "i" should only need to be a uint8_t
|
|
Some bug has occured using a newer version of the avr-gcc that
|
|
causes this routine to only delay 1ms if both "ms" and "i"
|
|
are uint8_t. */
|
|
uint16_t i;
|
|
|
|
for (i = 0; i < ms; i++)
|
|
{
|
|
DELAY_US (1000);
|
|
}
|
|
}
|
|
|
|
|
|
#endif /* DELAY_H */
|