$treeview $search $mathjax $extrastylesheet
avr-libc  2.0.0
$projectbrief
$projectbrief
$searchbox

AVR Libc Home Page

AVRs

AVR Libc Development Pages

Main Page

User Manual

Library Reference

FAQ

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$ */
00034 
00035 #ifndef _UTIL_DELAY_H_
00036 #define _UTIL_DELAY_H_ 1
00037 
00038 #ifndef __DOXYGEN__
00039 #  ifndef __HAS_DELAY_CYCLES
00040 #    define __HAS_DELAY_CYCLES 1
00041 #  endif
00042 #endif  /* __DOXYGEN__ */
00043 
00044 #include <inttypes.h>
00045 #include <util/delay_basic.h>
00046 #include <math.h>
00047 
00048 /** \file */
00049 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
00050     \code
00051     #define F_CPU 1000000UL  // 1 MHz
00052     //#define F_CPU 14.7456E6
00053     #include <util/delay.h>
00054     \endcode
00055 
00056     \note As an alternative method, it is possible to pass the
00057     F_CPU macro down to the compiler from the Makefile.
00058     Obviously, in that case, no \c \#define statement should be
00059     used.
00060 
00061     The functions in this header file are wrappers around the basic
00062     busy-wait functions from <util/delay_basic.h>.  They are meant as
00063     convenience functions where actual time values can be specified
00064     rather than a number of cycles to wait for.  The idea behind is
00065     that compile-time constant expressions will be eliminated by
00066     compiler optimization so floating-point expressions can be used
00067     to calculate the number of delay cycles needed based on the CPU
00068     frequency passed by the macro F_CPU.
00069 
00070     \note In order for these functions to work as intended, compiler
00071     optimizations <em>must</em> be enabled, and the delay time
00072     <em>must</em> be an expression that is a known constant at
00073     compile-time.  If these requirements are not met, the resulting
00074     delay will be much longer (and basically unpredictable), and
00075     applications that otherwise do not use floating-point calculations
00076     will experience severe code bloat by the floating-point library
00077     routines linked into the application.
00078 
00079     The functions available allow the specification of microsecond, and
00080     millisecond delays directly, using the application-supplied macro
00081     F_CPU as the CPU clock frequency (in Hertz).
00082 
00083 */
00084 
00085 #if !defined(__DOXYGEN__)
00086 static __inline__ void _delay_us(double __us) __attribute__((__always_inline__));
00087 static __inline__ void _delay_ms(double __ms) __attribute__((__always_inline__));
00088 #endif
00089 
00090 #ifndef F_CPU
00091 /* prevent compiler error by supplying a default */
00092 # warning "F_CPU not defined for <util/delay.h>"
00093 /** \ingroup util_delay
00094     \def F_CPU
00095     \brief CPU frequency in Hz
00096 
00097     The macro F_CPU specifies the CPU frequency to be considered by
00098     the delay macros.  This macro is normally supplied by the
00099     environment (e.g. from within a project header, or the project's
00100     Makefile).  The value 1 MHz here is only provided as a "vanilla"
00101     fallback if no such user-provided definition could be found.
00102 
00103     In terms of the delay functions, the CPU frequency can be given as
00104     a floating-point constant (e.g. 3.6864E6 for 3.6864 MHz).
00105     However, the macros in <util/setbaud.h> require it to be an
00106     integer value.
00107  */
00108 # define F_CPU 1000000UL
00109 #endif
00110 
00111 #ifndef __OPTIMIZE__
00112 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
00113 #endif
00114 
00115 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00116   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00117   __STDC_HOSTED__
00118 #  include <math.h>
00119 #endif
00120 
00121 /**
00122    \ingroup util_delay
00123 
00124    Perform a delay of \c __ms milliseconds, using _delay_loop_2().
00125 
00126    The macro F_CPU is supposed to be defined to a
00127    constant defining the CPU clock frequency (in Hertz).
00128 
00129    The maximal possible delay is 262.14 ms / F_CPU in MHz.
00130 
00131    When the user request delay which exceed the maximum possible one,
00132    _delay_ms() provides a decreased resolution functionality. In this
00133    mode _delay_ms() will work with a resolution of 1/10 ms, providing
00134    delays up to 6.5535 seconds (independent from CPU frequency).  The
00135    user will not be informed about decreased resolution.
00136 
00137    If the avr-gcc toolchain has __builtin_avr_delay_cycles()
00138    support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
00139    values greater than the maximal possible delay, overflows results in
00140    no delay i.e., 0ms.
00141 
00142    Conversion of \c __ms into clock cycles may not always result in
00143    integer.  By default, the clock cycles rounded up to next
00144    integer. This ensures that the user gets at least \c __ms
00145    microseconds of delay.
00146 
00147    Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
00148    \c __DELAY_ROUND_CLOSEST__, before including this header file, the
00149    algorithm can be made to round down, or round to closest integer,
00150    respectively.
00151 
00152    \note
00153 
00154    The implementation of _delay_ms() based on
00155    __builtin_avr_delay_cycles() is not backward compatible with older
00156    implementations.  In order to get functionality backward compatible
00157    with previous versions, the macro \c "__DELAY_BACKWARD_COMPATIBLE__"
00158    must be defined before including this header file. Also, the
00159    backward compatible algorithm will be chosen if the code is
00160    compiled in a <em>freestanding environment</em> (GCC option
00161    \c -ffreestanding), as the math functions required for rounding are
00162    not available to the compiler then.
00163 
00164  */
00165 void
00166 _delay_ms(double __ms)
00167 {
00168     double __tmp ;
00169 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00170   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00171   __STDC_HOSTED__
00172     uint32_t __ticks_dc;
00173     extern void __builtin_avr_delay_cycles(unsigned long);
00174     __tmp = ((F_CPU) / 1e3) * __ms;
00175 
00176     #if defined(__DELAY_ROUND_DOWN__)
00177         __ticks_dc = (uint32_t)fabs(__tmp);
00178 
00179     #elif defined(__DELAY_ROUND_CLOSEST__)
00180         __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00181 
00182     #else
00183         //round up by default
00184         __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00185     #endif
00186 
00187     __builtin_avr_delay_cycles(__ticks_dc);
00188 
00189 #else
00190     uint16_t __ticks;
00191     __tmp = ((F_CPU) / 4e3) * __ms;
00192     if (__tmp < 1.0)
00193         __ticks = 1;
00194     else if (__tmp > 65535)
00195     {
00196         //  __ticks = requested delay in 1/10 ms
00197         __ticks = (uint16_t) (__ms * 10.0);
00198         while(__ticks)
00199         {
00200             // wait 1/10 ms
00201             _delay_loop_2(((F_CPU) / 4e3) / 10);
00202             __ticks --;
00203         }
00204         return;
00205     }
00206     else
00207         __ticks = (uint16_t)__tmp;
00208     _delay_loop_2(__ticks);
00209 #endif
00210 }
00211 
00212 /**
00213    \ingroup util_delay
00214 
00215    Perform a delay of \c __us microseconds, using _delay_loop_1().
00216 
00217    The macro F_CPU is supposed to be defined to a
00218    constant defining the CPU clock frequency (in Hertz).
00219 
00220    The maximal possible delay is 768 us / F_CPU in MHz.
00221 
00222    If the user requests a delay greater than the maximal possible one,
00223    _delay_us() will automatically call _delay_ms() instead.  The user
00224    will not be informed about this case.
00225 
00226    If the avr-gcc toolchain has __builtin_avr_delay_cycles()
00227    support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For
00228    values greater than the maximal possible delay, overflow results in
00229    no delay i.e., 0us.
00230 
00231    Conversion of \c __us into clock cycles may not always result in
00232    integer.  By default, the clock cycles rounded up to next
00233    integer. This ensures that the user gets at least \c __us
00234    microseconds of delay.
00235 
00236    Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
00237    \c __DELAY_ROUND_CLOSEST__, before including this header file, the
00238    algorithm can be made to round down, or round to closest integer,
00239    respectively.
00240 
00241    \note
00242 
00243    The implementation of _delay_ms() based on
00244    __builtin_avr_delay_cycles() is not backward compatible with older
00245    implementations.  In order to get functionality backward compatible
00246    with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
00247    must be defined before including this header file. Also, the
00248    backward compatible algorithm will be chosen if the code is
00249    compiled in a <em>freestanding environment</em> (GCC option
00250    \c -ffreestanding), as the math functions required for rounding are
00251    not available to the compiler then.
00252 
00253  */
00254 void
00255 _delay_us(double __us)
00256 {
00257     double __tmp ;
00258 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
00259   !defined(__DELAY_BACKWARD_COMPATIBLE__) &&       \
00260   __STDC_HOSTED__
00261     uint32_t __ticks_dc;
00262     extern void __builtin_avr_delay_cycles(unsigned long);
00263     __tmp = ((F_CPU) / 1e6) * __us;
00264 
00265     #if defined(__DELAY_ROUND_DOWN__)
00266         __ticks_dc = (uint32_t)fabs(__tmp);
00267 
00268     #elif defined(__DELAY_ROUND_CLOSEST__)
00269         __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
00270 
00271     #else
00272         //round up by default
00273         __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
00274     #endif
00275 
00276     __builtin_avr_delay_cycles(__ticks_dc);
00277 
00278 #else
00279     uint8_t __ticks;
00280     double __tmp2 ;
00281     __tmp = ((F_CPU) / 3e6) * __us;
00282     __tmp2 = ((F_CPU) / 4e6) * __us;
00283     if (__tmp < 1.0)
00284         __ticks = 1;
00285     else if (__tmp2 > 65535)
00286     {
00287         _delay_ms(__us / 1000.0);
00288     }
00289     else if (__tmp > 255)
00290     {
00291         uint16_t __ticks=(uint16_t)__tmp2;
00292         _delay_loop_2(__ticks);
00293         return;
00294     }
00295     else
00296         __ticks = (uint8_t)__tmp;
00297     _delay_loop_1(__ticks);
00298 #endif
00299 }
00300 
00301 
00302 #endif /* _UTIL_DELAY_H_ */
 All Data Structures Files Functions Variables Typedefs Enumerations Defines