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_ */
void _delay_loop_2(uint16_t __count)
Definition: delay_basic.h:103
double fabs(double __x)
unsigned char uint8_t
Definition: stdint.h:79
void _delay_ms(double __ms)
Definition: delay.h:142
unsigned long int uint32_t
Definition: stdint.h:99
double ceil(double __x)
void _delay_us(double __us)
Definition: delay.h:224
void _delay_loop_1(uint8_t __count)
Definition: delay_basic.h:81
unsigned int uint16_t
Definition: stdint.h:89

Automatically generated by Doxygen 1.8.7 on Tue Jul 8 2014. Dash Docset conversion by Matt Kane