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_ */
|