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_8h_source.html,v 1.1.1.4 2012/01/03 16:04:22 joerg_wunsch Exp $ */
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 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00099   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00100   __STDC_HOSTED__
00101 #  include <math.h>
00102 #endif
00103 
00104 /**
00105    \ingroup util_delay
00106 
00107    Perform a delay of \c __ms milliseconds, using _delay_loop_2().
00108 
00109    The macro F_CPU is supposed to be defined to a
00110    constant defining the CPU clock frequency (in Hertz).
00111 
00112    The maximal possible delay is 262.14 ms / F_CPU in MHz.
00113 
00114    When the user request delay which exceed the maximum possible one,
00115    _delay_ms() provides a decreased resolution functionality. In this
00116    mode _delay_ms() will work with a resolution of 1/10 ms, providing
00117    delays up to 6.5535 seconds (independent from CPU frequency).  The
00118    user will not be informed about decreased resolution.
00119 
00120    If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
00121    support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
00122    values greater than the maximal possible delay, overflows results in
00123    no delay i.e., 0ms.
00124 
00125    Conversion of __us into clock cycles may not always result in integer.
00126    By default, the clock cycles rounded up to next integer. This ensures that
00127    the user gets atleast __us microseconds of delay.
00128 
00129    Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
00130    to round down and round to closest integer.
00131 
00132    Note: The new implementation of _delay_ms(double __ms) with 
00133     __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 
00134    User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay.
00135    Also, the backward compatible
00136    algorithm will be chosen if the code is compiled in a <em>freestanding
00137    environment</em> (GCC option \c -ffreestanding), as the math functions
00138    required for rounding are not available to the compiler then.
00139 
00140  */
00141 void
00142 _delay_ms(double __ms)
00143 {
00144         uint16_t __ticks;
00145         double __tmp ; 
00146 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00147   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00148   __STDC_HOSTED__
00149         uint32_t __ticks_dc;
00150         extern void __builtin_avr_delay_cycles(unsigned long);
00151         __tmp = ((F_CPU) / 1e3) * __ms;
00152 
00153         #if defined(__DELAY_ROUND_DOWN__)
00154                 __ticks_dc = (uint32_t)fabs(__tmp);
00155 
00156         #elif defined(__DELAY_ROUND_CLOSEST__)
00157                 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00158 
00159         #else
00160                 //round up by default
00161                 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00162         #endif
00163 
00164         __builtin_avr_delay_cycles(__ticks_dc);
00165 
00166 #else
00167         __tmp = ((F_CPU) / 4e3) * __ms;
00168         if (__tmp < 1.0)
00169                 __ticks = 1;
00170         else if (__tmp > 65535)
00171         {
00172                 //      __ticks = requested delay in 1/10 ms
00173                 __ticks = (uint16_t) (__ms * 10.0);
00174                 while(__ticks)
00175                 {
00176                         // wait 1/10 ms
00177                         _delay_loop_2(((F_CPU) / 4e3) / 10);
00178                         __ticks --;
00179                 }
00180                 return;
00181         }
00182         else
00183                 __ticks = (uint16_t)__tmp;
00184         _delay_loop_2(__ticks);
00185 #endif
00186 }
00187 
00188 /**
00189    \ingroup util_delay
00190 
00191    Perform a delay of \c __us microseconds, using _delay_loop_1().
00192 
00193    The macro F_CPU is supposed to be defined to a
00194    constant defining the CPU clock frequency (in Hertz).
00195 
00196    The maximal possible delay is 768 us / F_CPU in MHz.
00197 
00198    If the user requests a delay greater than the maximal possible one,
00199    _delay_us() will automatically call _delay_ms() instead.  The user
00200    will not be informed about this case.
00201 
00202    If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long)
00203    support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For
00204    values greater than the maximal possible delay, overflow results in
00205    no delay i.e., 0us.
00206   
00207    Conversion of __us into clock cycles may not always result in integer.
00208    By default, the clock cycles rounded up to next integer. This ensures that
00209    the user gets atleast __us microseconds of delay.
00210 
00211    Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__
00212    to round down and round to closest integer.
00213  
00214    Note: The new implementation of _delay_us(double __us) with 
00215     __builtin_avr_delay_cycles(unsigned long) support is not backward compatible.
00216    User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay.
00217    Also, the backward compatible
00218    algorithm will be chosen if the code is compiled in a <em>freestanding
00219    environment</em> (GCC option \c -ffreestanding), as the math functions
00220    required for rounding are not available to the compiler then.
00221 
00222  */
00223 void
00224 _delay_us(double __us)
00225 {
00226         uint8_t __ticks;
00227         double __tmp ; 
00228 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00229   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00230   __STDC_HOSTED__
00231         uint32_t __ticks_dc;
00232         extern void __builtin_avr_delay_cycles(unsigned long);
00233         __tmp = ((F_CPU) / 1e6) * __us;
00234 
00235         #if defined(__DELAY_ROUND_DOWN__)
00236                 __ticks_dc = (uint32_t)fabs(__tmp);
00237 
00238         #elif defined(__DELAY_ROUND_CLOSEST__)
00239                 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00240 
00241         #else
00242                 //round up by default
00243                 __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00244         #endif
00245 
00246         __builtin_avr_delay_cycles(__ticks_dc);
00247 
00248 #else
00249         __tmp = ((F_CPU) / 3e6) * __us;
00250         if (__tmp < 1.0)
00251                 __ticks = 1;
00252         else if (__tmp > 255)
00253         {
00254                 _delay_ms(__us / 1000.0);
00255                 return;
00256         }
00257         else
00258                 __ticks = (uint8_t)__tmp;
00259         _delay_loop_1(__ticks);
00260 #endif
00261 }
00262 
00263 
00264 #endif /* _UTIL_DELAY_H_ */

Automatically generated by Doxygen 1.7.6.1 on Tue Jan 3 2012.