delay.h


1
#ifndef _UTIL_DELAY_H_
2
#define _UTIL_DELAY_H_ 1
3
4
#include <inttypes.h>
5
#include <util/delay_basic.h>
6
7
/** \file */
8
/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
9
    \code
10
    #define F_CPU 1000000UL  // 1 MHz
11
    //#define F_CPU 14.7456E6
12
    #include <util/delay.h>
13
    \endcode
14
15
    \note As an alternative method, it is possible to pass the
16
    F_CPU macro down to the compiler from the Makefile.
17
    Obviously, in that case, no \c \#define statement should be
18
    used.
19
20
    The functions in this header file are wrappers around the basic
21
    busy-wait functions from <util/delay_basic.h>.  They are meant as
22
    convenience functions where actual time values can be specified
23
    rather than a number of cycles to wait for.  The idea behind is
24
    that compile-time constant expressions will be eliminated by
25
    compiler optimization so floating-point expressions can be used
26
    to calculate the number of delay cycles needed based on the CPU
27
    frequency passed by the macro F_CPU.
28
29
    \note In order for these functions to work as intended, compiler
30
    optimizations <em>must</em> be enabled, and the delay time
31
    <em>must</em> be an expression that is a known constant at
32
    compile-time.  If these requirements are not met, the resulting
33
    delay will be much longer (and basically unpredictable), and
34
    applications that otherwise do not use floating-point calculations
35
    will experience severe code bloat by the floating-point library
36
    routines linked into the application.
37
38
    The functions available allow the specification of microsecond, and
39
    millisecond delays directly, using the application-supplied macro
40
    F_CPU as the CPU clock frequency (in Hertz).
41
42
*/
43
44
#if !defined(__DOXYGEN__)
45
static inline void _delay_us(double __us) __attribute__((always_inline));
46
static inline void _delay_ms(double __ms) __attribute__((always_inline));
47
#endif
48
49
#ifndef F_CPU
50
/* prevent compiler error by supplying a default */
51
# warning "F_CPU not defined for <util/delay.h>"
52
# define F_CPU 1000000UL
53
#endif
54
55
#ifndef __OPTIMIZE__
56
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
57
#endif
58
59
/**
60
   \ingroup util_delay
61
62
   Perform a delay of \c __us microseconds, using _delay_loop_1().
63
64
   The macro F_CPU is supposed to be defined to a
65
   constant defining the CPU clock frequency (in Hertz).
66
67
   The maximal possible delay is 768 us / F_CPU in MHz.
68
 */
69
void
70
_delay_us(double __us)
71
{
72
  uint8_t __ticks;
73
  double __tmp = ((F_CPU) / 3e6) * __us;
74
  if (__tmp < 1.0)
75
    __ticks = 1;
76
  else if (__tmp > 255)
77
    __ticks = 0;  /* i.e. 256 */
78
  else
79
    __ticks = (uint8_t)__tmp;
80
  _delay_loop_1(__ticks);
81
}
82
83
84
/**
85
   \ingroup util_delay
86
87
   Perform a delay of \c __ms milliseconds, using _delay_loop_2().
88
89
   The macro F_CPU is supposed to be defined to a
90
   constant defining the CPU clock frequency (in Hertz).
91
92
   The maximal possible delay is 262.14 ms / F_CPU in MHz.
93
 */
94
void
95
_delay_ms(double __ms)
96
{
97
  uint16_t __ticks;
98
  double __tmp = ((F_CPU) / 4e3) * __ms;
99
  if (__tmp < 1.0)
100
    __ticks = 1;
101
  else if (__tmp > 65535)
102
    __ticks = 0;  /* i.e. 65536 */
103
  else
104
    __ticks = (uint16_t)__tmp;
105
  _delay_loop_2(__ticks);
106
}
107
108
#endif /* _UTIL_DELAY_H_ */