AVR Libc Home Page |  | AVR Libc Development Pages
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects

delay.h
Go to the documentation of this file.
1 /* Copyright (c) 2002, Marek Michalkiewicz
2 Copyright (c) 2004,2005,2007 Joerg Wunsch
3 Copyright (c) 2007 Florin-Viorel Petrov
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * Neither the name of the copyright holders nor the names of
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
32
33 /* $Id: delay.h.in 2251 2011-09-14 08:20:33Z joerg_wunsch $ */
34
35 #ifndef _UTIL_DELAY_H_
36 #define _UTIL_DELAY_H_ 1
37
38 #ifndef __HAS_DELAY_CYCLES
39 #define __HAS_DELAY_CYCLES 1
40 #endif
41
42 #include <inttypes.h>
43 #include <util/delay_basic.h>
44 #include <math.h>
45
46 /** \file */
47 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
48 \code
49 #define F_CPU 1000000UL // 1 MHz
50 //#define F_CPU 14.7456E6
51 #include <util/delay.h>
52 \endcode
53
54 \note As an alternative method, it is possible to pass the
55 F_CPU macro down to the compiler from the Makefile.
56 Obviously, in that case, no \c \#define statement should be
57 used.
58
59 The functions in this header file are wrappers around the basic
60 busy-wait functions from <util/delay_basic.h>. They are meant as
61 convenience functions where actual time values can be specified
62 rather than a number of cycles to wait for. The idea behind is
63 that compile-time constant expressions will be eliminated by
64 compiler optimization so floating-point expressions can be used
65 to calculate the number of delay cycles needed based on the CPU
66 frequency passed by the macro F_CPU.
67
68 \note In order for these functions to work as intended, compiler
69 optimizations <em>must</em> be enabled, and the delay time
70 <em>must</em> be an expression that is a known constant at
71 compile-time. If these requirements are not met, the resulting
72 delay will be much longer (and basically unpredictable), and
73 applications that otherwise do not use floating-point calculations
74 will experience severe code bloat by the floating-point library
75 routines linked into the application.
76
77 The functions available allow the specification of microsecond, and
78 millisecond delays directly, using the application-supplied macro
79 F_CPU as the CPU clock frequency (in Hertz).
80
81 */
82
83 #if !defined(__DOXYGEN__)
84 static inline void _delay_us(double __us) __attribute__((always_inline));
85 static inline void _delay_ms(double __ms) __attribute__((always_inline));
86 #endif
87
88 #ifndef F_CPU
89 /* prevent compiler error by supplying a default */
90 # warning "F_CPU not defined for <util/delay.h>"
91 # define F_CPU 1000000UL
92 #endif
93
94 #ifndef __OPTIMIZE__
95 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
96 #endif
97
98 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
99 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
100 __STDC_HOSTED__
101 # include <math.h>
102 #endif
103
104 /**
105 \ingroup util_delay
106
107 Perform a delay of \c __ms milliseconds, using _delay_loop_2().
108
109 The macro F_CPU is supposed to be defined to a
110 constant defining the CPU clock frequency (in Hertz).
111
112 The maximal possible delay is 262.14 ms / F_CPU in MHz.
113
114 When the user request delay which exceed the maximum possible one,
115 _delay_ms() provides a decreased resolution functionality. In this
116 mode _delay_ms() will work with a resolution of 1/10 ms, providing
117 delays up to 6.5535 seconds (independent from CPU frequency). The
118 user will not be informed about decreased resolution.
119
120 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
121 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
122 values greater than the maximal possible delay, overflows results in
123 no delay i.e., 0ms.
124
125 Conversion of __us into clock cycles may not always result in integer.
126 By default, the clock cycles rounded up to next integer. This ensures that
127 the user gets atleast __us microseconds of delay.
128
129 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
130 to round down and round to closest integer.
131
132 Note: The new implementation of _delay_ms(double __ms) with
133 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible.
134 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay.
135 Also, the backward compatible
136 algorithm will be chosen if the code is compiled in a <em>freestanding
137 environment</em> (GCC option \c -ffreestanding), as the math functions
138 required for rounding are not available to the compiler then.
139
140 */
141 void
142 _delay_ms(double __ms)
143 {
144 uint16_t __ticks;
145 double __tmp ;
146 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
147 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
148 __STDC_HOSTED__
149 uint32_t __ticks_dc;
150 extern void __builtin_avr_delay_cycles(unsigned long);
151 __tmp = ((F_CPU) / 1e3) * __ms;
152
153 #if defined(__DELAY_ROUND_DOWN__)
154 __ticks_dc = (uint32_t)fabs(__tmp);
155
156 #elif defined(__DELAY_ROUND_CLOSEST__)
157 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
158
159 #else
160 //round up by default
161 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
162 #endif
163
164 __builtin_avr_delay_cycles(__ticks_dc);
165
166 #else
167 __tmp = ((F_CPU) / 4e3) * __ms;
168 if (__tmp < 1.0)
169 __ticks = 1;
170 else if (__tmp > 65535)
171 {
172 // __ticks = requested delay in 1/10 ms
173 __ticks = (uint16_t) (__ms * 10.0);
174 while(__ticks)
175 {
176 // wait 1/10 ms
177 _delay_loop_2(((F_CPU) / 4e3) / 10);
178 __ticks --;
179 }
180 return;
181 }
182 else
183 __ticks = (uint16_t)__tmp;
184 _delay_loop_2(__ticks);
185 #endif
186 }
187
188 /**
189 \ingroup util_delay
190
191 Perform a delay of \c __us microseconds, using _delay_loop_1().
192
193 The macro F_CPU is supposed to be defined to a
194 constant defining the CPU clock frequency (in Hertz).
195
196 The maximal possible delay is 768 us / F_CPU in MHz.
197
198 If the user requests a delay greater than the maximal possible one,
199 _delay_us() will automatically call _delay_ms() instead. The user
200 will not be informed about this case.
201
202 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
203 support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For
204 values greater than the maximal possible delay, overflow results in
205 no delay i.e., 0us.
206
207 Conversion of __us into clock cycles may not always result in integer.
208 By default, the clock cycles rounded up to next integer. This ensures that
209 the user gets atleast __us microseconds of delay.
210
211 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
212 to round down and round to closest integer.
213
214 Note: The new implementation of _delay_us(double __us) with
215 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible.
216 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay.
217 Also, the backward compatible
218 algorithm will be chosen if the code is compiled in a <em>freestanding
219 environment</em> (GCC option \c -ffreestanding), as the math functions
220 required for rounding are not available to the compiler then.
221
222 */
223 void
224 _delay_us(double __us)
225 {
226 uint8_t __ticks;
227 double __tmp ;
228 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
229 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \
230 __STDC_HOSTED__
231 uint32_t __ticks_dc;
232 extern void __builtin_avr_delay_cycles(unsigned long);
233 __tmp = ((F_CPU) / 1e6) * __us;
234
235 #if defined(__DELAY_ROUND_DOWN__)
236 __ticks_dc = (uint32_t)fabs(__tmp);
237
238 #elif defined(__DELAY_ROUND_CLOSEST__)
239 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
240
241 #else
242 //round up by default
243 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
244 #endif
245
246 __builtin_avr_delay_cycles(__ticks_dc);
247
248 #else
249 __tmp = ((F_CPU) / 3e6) * __us;
250 if (__tmp < 1.0)
251 __ticks = 1;
252 else if (__tmp > 255)
253 {
254 _delay_ms(__us / 1000.0);
255 return;
256 }
257 else
258 __ticks = (uint8_t)__tmp;
259 _delay_loop_1(__ticks);
260 #endif
261 }
262
263
264 #endif /* _UTIL_DELAY_H_ */

Automatically generated by Doxygen 1.8.3.1 on Sat Sep 14 2013.