delay.h


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,v 1.5 2007/10/28 23:25:56 joerg_wunsch Exp $ */
34
35
#ifndef _UTIL_DELAY_H_
36
#define _UTIL_DELAY_H_ 1
37
38
#include <inttypes.h>
39
#include <util/delay_basic.h>
40
41
/** \file */
42
/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
43
    \code
44
    #define F_CPU 1000000UL  // 1 MHz
45
    //#define F_CPU 14.7456E6
46
    #include <util/delay.h>
47
    \endcode
48
49
    \note As an alternative method, it is possible to pass the
50
    F_CPU macro down to the compiler from the Makefile.
51
    Obviously, in that case, no \c \#define statement should be
52
    used.
53
54
    The functions in this header file are wrappers around the basic
55
    busy-wait functions from <util/delay_basic.h>.  They are meant as
56
    convenience functions where actual time values can be specified
57
    rather than a number of cycles to wait for.  The idea behind is
58
    that compile-time constant expressions will be eliminated by
59
    compiler optimization so floating-point expressions can be used
60
    to calculate the number of delay cycles needed based on the CPU
61
    frequency passed by the macro F_CPU.
62
63
    \note In order for these functions to work as intended, compiler
64
    optimizations <em>must</em> be enabled, and the delay time
65
    <em>must</em> be an expression that is a known constant at
66
    compile-time.  If these requirements are not met, the resulting
67
    delay will be much longer (and basically unpredictable), and
68
    applications that otherwise do not use floating-point calculations
69
    will experience severe code bloat by the floating-point library
70
    routines linked into the application.
71
72
    The functions available allow the specification of microsecond, and
73
    millisecond delays directly, using the application-supplied macro
74
    F_CPU as the CPU clock frequency (in Hertz).
75
76
*/
77
78
#if !defined(__DOXYGEN__)
79
static inline void _delay_us(double __us) __attribute__((always_inline));
80
static inline void _delay_ms(double __ms) __attribute__((always_inline));
81
#endif
82
83
#ifndef F_CPU
84
/* prevent compiler error by supplying a default */
85
# warning "F_CPU not defined for <util/delay.h>"
86
# define F_CPU 1000000UL
87
#endif
88
89
#ifndef __OPTIMIZE__
90
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
91
#endif
92
93
/**
94
   \ingroup util_delay
95
96
   Perform a delay of \c __us microseconds, using _delay_loop_1().
97
98
   The macro F_CPU is supposed to be defined to a
99
   constant defining the CPU clock frequency (in Hertz).
100
101
   The maximal possible delay is 768 us / F_CPU in MHz.
102
103
   If the user requests a delay greater than the maximal possible one,
104
   _delay_us() will automatically call _delay_ms() instead.  The user
105
   will not be informed about this case.
106
 */
107
void
108
_delay_us(double __us)
109
{
110
  uint8_t __ticks;
111
  double __tmp = ((F_CPU) / 3e6) * __us;
112
  if (__tmp < 1.0)
113
    __ticks = 1;
114
  else if (__tmp > 255)
115
  {
116
    _delay_ms(__us / 1000.0);
117
    return;
118
  }
119
  else
120
    __ticks = (uint8_t)__tmp;
121
  _delay_loop_1(__ticks);
122
}
123
124
125
/**
126
   \ingroup util_delay
127
128
   Perform a delay of \c __ms milliseconds, using _delay_loop_2().
129
130
   The macro F_CPU is supposed to be defined to a
131
   constant defining the CPU clock frequency (in Hertz).
132
133
   The maximal possible delay is 262.14 ms / F_CPU in MHz.
134
135
   When the user request delay which exceed the maximum possible one,
136
   _delay_ms() provides a decreased resolution functionality. In this
137
   mode _delay_ms() will work with a resolution of 1/10 ms, providing
138
   delays up to 6.5535 seconds (independent from CPU frequency).  The
139
   user will not be informed about decreased resolution.
140
 */
141
void
142
_delay_ms(double __ms)
143
{
144
  uint16_t __ticks;
145
  double __tmp = ((F_CPU) / 4e3) * __ms;
146
  if (__tmp < 1.0)
147
    __ticks = 1;
148
  else if (__tmp > 65535)
149
  {
150
    //  __ticks = requested delay in 1/10 ms
151
    __ticks = (uint16_t) (__ms * 10.0);
152
    while(__ticks)
153
    {
154
      // wait 1/10 ms
155
      _delay_loop_2(((F_CPU) / 4e3) / 10);
156
      __ticks --;
157
    }
158
    return;
159
  }
160
  else
161
    __ticks = (uint16_t)__tmp;
162
  _delay_loop_2(__ticks);
163
}
164
165
#endif /* _UTIL_DELAY_H_ */