Specific the directory for all hw and cfg module. Use double quote for cfg and hw...
[bertos.git] / bertos / algo / ramp.h
1
2 /**
3  * \file
4  * <!--
5  * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
6  * All Rights Reserved.
7  * -->
8  *
9  * \brief Compute, save and load ramps for stepper motors (interace)
10  *
11  * \version $Id$
12  *
13  * \author Simone Zinanni <s.zinanni@develer.com>
14  * \author Giovanni Bajo <rasky@develer.com>
15  * \author Daniele Basile <asterix@develer.com>
16  *
17  * The acceleration ramp is used to properly accelerate a stepper motor. The main
18  * entry point is the function ramp_evaluate(), which must be called at every step
19  * of the motor: it gets as input the time elapsed since the stepper started
20  * accelerating, and returns the time to wait before sending the next step. A pseudo
21  * usage pattern is as follows:
22  *
23  * <pre>
24  *  float time = 0;
25  *  while (1)
26  *  {
27  *      float delta = ramp_evaluate(&my_ramp, time);
28  *      sleep(delta);
29  *      do_motor_step();
30  *      time += delta;
31  *  }
32  * </pre>
33  *
34  * A similar pattern can be used to decelerate (it is sufficient to move the total
35  * time backward, such as "time -= delta").
36  *
37  * The ramp can be configured with ramp_setup(), providing it with the minimum and
38  * maximum operating frequency of the motor, and the total acceleration time in
39  * milliseconds (that is, the time that will be needed to accelerate from the
40  * minimum frequency to the maximum frequency).
41  *
42  * Both a very precise floating point and a very fast fixed point implementation
43  * of the ramp evaluation are provided. The fixed point is hand-optimized assembly
44  * for DSP56000 (but a portable C version of it can be easily written, see the
45  * comments in the code).
46  *
47  */
48
49 #ifndef ALGO_RAMP_H
50 #define ALGO_RAMP_H
51
52 #include "hw/hw_stepper.h"
53
54 #include <cfg/compiler.h>
55
56 /**
57  * Define whether the ramp will use floating point calculation within ramp_evaluate().
58  * Otherwise, a less precise fixed point version will be used, which is faster on
59  * platforms which do no support floating point operations.
60  *
61  * \note Floating point operations will be always done within ramp_compute() to
62  * precalculate values, so there has to be at least a floating point emulation support.
63  */
64 #define RAMP_USE_FLOATING_POINT   0
65
66
67 #if !RAMP_USE_FLOATING_POINT
68
69         /**
70          * Number of least-significant bits which are stripped away during ramp evaluation.
71          * This setting allows to specify larger ramps at the price of less precision.
72          *
73          * The maximum ramp size allowed is 2^(24 + RAMP_CLOCK_SHIFT_PRECISION), in clocks.
74          * For instance, using RAMP_CLOCK_SHIFT_PRECISION 1, and a 8x prescaler, the maximum
75          * length of a ramp is about 6.7 secs. Raising RAMP_CLOCK_SHIFT_PRECISION to 2
76          * brings the maximum length to 13.4 secs, at the price of less precision.
77          *
78          * ramp_compute() will check that the length is below the maximum allowed through
79          * a runtime assertion.
80          *
81          * \note This macro is used only for the fixed-point version of the ramp.
82          */
83         #define RAMP_CLOCK_SHIFT_PRECISION 2
84 #endif
85
86
87 ///< Negative pulse width for ramp
88 #define RAMP_PULSE_WIDTH    50
89
90 ///< Default ramp
91 #define RAMP_DEF_TIME       6000000 ///< microsecs
92 #define RAMP_DEF_MAXFREQ       5000 ///< Hz
93 #define RAMP_DEF_MINFREQ        200 ///< Hz
94 #define RAMP_DEF_POWERRUN        10 ///< 10 deciampere (1 ampere)
95 #define RAMP_DEF_POWERIDLE        1 ///< 1 deciampere
96
97
98 /**
99  * Convert microseconds to timer clock ticks
100  */
101 #define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000))
102
103 /**
104  * Convert timer clock ticks back to microseconds
105  */
106 #define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000))
107
108 /**
109  * Convert microseconds to Hz
110  */
111 #define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros)))
112
113 /**
114  * Convert frequency (in Hz) to time (in microseconds)
115  */
116 #define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz)))
117
118 /**
119  * Multiply \p a and \p b two integer at 32 bit and extract the high 16 bit word.
120  */
121 #define FIX_MULT32(a,b)  (((uint64_t)(a)*(uint32_t)(b)) >> 16)
122
123 /**
124  * Structure holding pre-calculated data for speeding up real-time evaluation
125  * of the ramp. This structure is totally different between the fixed and the
126  * floating point version of the code.
127  *
128  * Consult the file-level documentation of ramp.c for more information about
129  * the values of this structure.
130  */
131 struct RampPrecalc
132 {
133 #if RAMP_USE_FLOATING_POINT
134         float beta;
135         float alpha;
136         float gamma;
137 #else
138         uint16_t max_div_min;
139         uint32_t inv_total_time;
140 #endif
141 };
142
143
144 /**
145  * Ramp structure
146  */
147 struct Ramp
148 {
149         uint32_t clocksRamp;
150         uint16_t clocksMinWL;
151         uint16_t clocksMaxWL;
152
153         struct RampPrecalc precalc; ///< pre-calculated values for speed
154 };
155
156
157 /*
158  * Function prototypes
159  */
160 void ramp_compute(
161         struct Ramp * ramp,
162         uint32_t clocksInRamp,
163         uint16_t clocksInMinWavelength,
164         uint16_t clocksInMaxWavelength);
165
166
167 /** Setup an acceleration ramp for a stepper motor
168  *
169  *  \param ramp Ramp to fill
170  *  \param length Length of the ramp (milliseconds)
171  *  \param minFreq Minimum operating frequency of the motor (hertz)
172  *  \param maxFreq Maximum operating frequency of the motor (hertz)
173  *
174  */
175 void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq);
176
177
178 /**
179  * Initialize a new ramp with default values
180  */
181 void ramp_default(struct Ramp *ramp);
182
183
184 /**
185  * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since
186  * the start of the acceleration, compute the next step, that is the interval at which
187  * send the signal to the motor.
188  *
189  * \note The fixed point version does not work when curClock is zero. Anyway,
190  * the first step is always clocksMaxWL, as stored within the ramp structure.
191  */
192 #if RAMP_USE_FLOATING_POINT
193         float ramp_evaluate(const struct Ramp* ramp, float curClock);
194 #else
195         uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock);
196 #endif
197
198
199 /** Self test */
200 void ramp_test(void);
201
202 #endif /* ALGO_RAMP_H */
203