sunu

delay.h

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