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

delay.h
Go to the documentation of this file.
00001 /* Copyright (c) 2002, Marek Michalkiewicz
00002    Copyright (c) 2004,2005,2007 Joerg Wunsch
00003    Copyright (c) 2007  Florin-Viorel Petrov
00004    All rights reserved.
00005 
00006    Redistribution and use in source and binary forms, with or without
00007    modification, are permitted provided that the following conditions are met:
00008 
00009    * Redistributions of source code must retain the above copyright
00010      notice, this list of conditions and the following disclaimer.
00011 
00012    * Redistributions in binary form must reproduce the above copyright
00013      notice, this list of conditions and the following disclaimer in
00014      the documentation and/or other materials provided with the
00015      distribution.
00016 
00017    * Neither the name of the copyright holders nor the names of
00018      contributors may be used to endorse or promote products derived
00019      from this software without specific prior written permission.
00020 
00021   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00022   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00025   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00026   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00027   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00029   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00030   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031   POSSIBILITY OF SUCH DAMAGE. */
00032 
00033 /* $Id: delay.h.in 2189 2010-10-13 09:39:34Z aboyapati $ */
00034 
00035 #ifndef _UTIL_DELAY_H_
00036 #define _UTIL_DELAY_H_ 1
00037 
00038 #ifndef __HAS_DELAY_CYCLES
00039 #define __HAS_DELAY_CYCLES 1
00040 #endif
00041 
00042 #include <inttypes.h>
00043 #include <util/delay_basic.h>
00044 #include <math.h>
00045 
00046 /** \file */
00047 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
00048     \code
00049     #define F_CPU 1000000UL  // 1 MHz
00050     //#define F_CPU 14.7456E6
00051     #include <util/delay.h>
00052     \endcode
00053 
00054     \note As an alternative method, it is possible to pass the
00055     F_CPU macro down to the compiler from the Makefile.
00056     Obviously, in that case, no \c \#define statement should be
00057     used.
00058 
00059     The functions in this header file are wrappers around the basic
00060     busy-wait functions from <util/delay_basic.h>.  They are meant as
00061     convenience functions where actual time values can be specified
00062     rather than a number of cycles to wait for.  The idea behind is
00063     that compile-time constant expressions will be eliminated by
00064     compiler optimization so floating-point expressions can be used
00065     to calculate the number of delay cycles needed based on the CPU
00066     frequency passed by the macro F_CPU.
00067 
00068     \note In order for these functions to work as intended, compiler
00069     optimizations <em>must</em> be enabled, and the delay time
00070     <em>must</em> be an expression that is a known constant at
00071     compile-time.  If these requirements are not met, the resulting
00072     delay will be much longer (and basically unpredictable), and
00073     applications that otherwise do not use floating-point calculations
00074     will experience severe code bloat by the floating-point library
00075     routines linked into the application.
00076 
00077     The functions available allow the specification of microsecond, and
00078     millisecond delays directly, using the application-supplied macro
00079     F_CPU as the CPU clock frequency (in Hertz).
00080 
00081 */
00082 
00083 #if !defined(__DOXYGEN__)
00084 static inline void _delay_us(double __us) __attribute__((always_inline));
00085 static inline void _delay_ms(double __ms) __attribute__((always_inline));
00086 #endif
00087 
00088 #ifndef F_CPU
00089 /* prevent compiler error by supplying a default */
00090 # warning "F_CPU not defined for <util/delay.h>"
00091 # define F_CPU 1000000UL
00092 #endif
00093 
00094 #ifndef __OPTIMIZE__
00095 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
00096 #endif
00097 
00098 /**
00099    \ingroup util_delay
00100 
00101    Perform a delay of \c __ms milliseconds, using _delay_loop_2().
00102 
00103    The macro F_CPU is supposed to be defined to a
00104    constant defining the CPU clock frequency (in Hertz).
00105 
00106    The maximal possible delay is 262.14 ms / F_CPU in MHz.
00107 
00108    When the user request delay which exceed the maximum possible one,
00109    _delay_ms() provides a decreased resolution functionality. In this
00110    mode _delay_ms() will work with a resolution of 1/10 ms, providing
00111    delays up to 6.5535 seconds (independent from CPU frequency).  The
00112    user will not be informed about decreased resolution.
00113 
00114    If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
00115    support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
00116    values greater than the maximal possible delay, overflows results in
00117    no delay i.e., 0ms.
00118 
00119    Conversion of __us into clock cycles may not always result in integer.
00120    By default, the clock cycles rounded up to next integer. This ensures that
00121    the user gets atleast __us microseconds of delay.
00122 
00123    Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
00124    to round down and round to closest integer.
00125 
00126    Note: The new implementation of _delay_ms(double __ms) with 
00127     __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 
00128    User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay
00129    although this will be deprecated in future.
00130 
00131  */
00132 void
00133 _delay_ms(double __ms)
00134 {
00135         uint16_t __ticks;
00136         double __tmp ; 
00137 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__)
00138         uint32_t __ticks_dc;
00139         extern void __builtin_avr_delay_cycles(unsigned long);
00140         __tmp = ((F_CPU) / 1e3) * __ms;
00141 
00142         #if defined(__DELAY_ROUND_DOWN__)
00143                 __ticks_dc = (uint32_t)fabs(__tmp);
00144 
00145         #elif defined(__DELAY_ROUND_CLOSEST__)
00146                 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00147 
00148         #else
00149                 //round up by default
00150                 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00151         #endif
00152 
00153         __builtin_avr_delay_cycles(__ticks_dc);
00154 
00155 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__)
00156         __tmp = ((F_CPU) / 4e3) * __ms;
00157         if (__tmp < 1.0)
00158                 __ticks = 1;
00159         else if (__tmp > 65535)
00160         {
00161                 //      __ticks = requested delay in 1/10 ms
00162                 __ticks = (uint16_t) (__ms * 10.0);
00163                 while(__ticks)
00164                 {
00165                         // wait 1/10 ms
00166                         _delay_loop_2(((F_CPU) / 4e3) / 10);
00167                         __ticks --;
00168                 }
00169                 return;
00170         }
00171         else
00172                 __ticks = (uint16_t)__tmp;
00173         _delay_loop_2(__ticks);
00174 #endif
00175 }
00176 
00177 /**
00178    \ingroup util_delay
00179 
00180    Perform a delay of \c __us microseconds, using _delay_loop_1().
00181 
00182    The macro F_CPU is supposed to be defined to a
00183    constant defining the CPU clock frequency (in Hertz).
00184 
00185    The maximal possible delay is 768 us / F_CPU in MHz.
00186 
00187    If the user requests a delay greater than the maximal possible one,
00188    _delay_us() will automatically call _delay_ms() instead.  The user
00189    will not be informed about this case.
00190 
00191    If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
00192    support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For
00193    values greater than the maximal possible delay, overflow results in
00194    no delay i.e., 0us.
00195   
00196    Conversion of __us into clock cycles may not always result in integer.
00197    By default, the clock cycles rounded up to next integer. This ensures that
00198    the user gets atleast __us microseconds of delay.
00199 
00200    Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
00201    to round down and round to closest integer.
00202  
00203    Note: The new implementation of _delay_us(double __us) with 
00204     __builtin_avr_delay_cycles(unsigned long) support is not backward compatible.
00205    User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay
00206    although this will be deprecated in future.
00207 
00208  */
00209 void
00210 _delay_us(double __us)
00211 {
00212         uint8_t __ticks;
00213         double __tmp ; 
00214 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__)
00215         uint32_t __ticks_dc;
00216         extern void __builtin_avr_delay_cycles(unsigned long);
00217         __tmp = ((F_CPU) / 1e6) * __us;
00218 
00219         #if defined(__DELAY_ROUND_DOWN__)
00220                 __ticks_dc = (uint32_t)fabs(__tmp);
00221 
00222         #elif defined(__DELAY_ROUND_CLOSEST__)
00223                 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00224 
00225         #else
00226                 //round up by default
00227                 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00228         #endif
00229 
00230         __builtin_avr_delay_cycles(__ticks_dc);
00231 
00232 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__)
00233         __tmp = ((F_CPU) / 3e6) * __us;
00234         if (__tmp < 1.0)
00235                 __ticks = 1;
00236         else if (__tmp > 255)
00237         {
00238                 _delay_ms(__us / 1000.0);
00239                 return;
00240         }
00241         else
00242                 __ticks = (uint8_t)__tmp;
00243         _delay_loop_1(__ticks);
00244 #endif
00245 }
00246 
00247 
00248 #endif /* _UTIL_DELAY_H_ */

Automatically generated by Doxygen 1.7.4 on Wed Aug 10 2011.