Silent nightly test warning.
[bertos.git] / bertos / algo / ramp.h
1 /**
2  * \file
3  * <!--
4  * Copyright 2004, 2008 Develer S.r.l. (http://www.develer.com/)
5  * All Rights Reserved.
6  * -->
7  *
8  * \brief Compute, save and load ramps for stepper motors.
9  *
10  * The acceleration ramp is used to properly accelerate a stepper motor. The main
11  * entry point is the function ramp_evaluate(), which must be called at every step
12  * of the motor: it gets as input the time elapsed since the stepper started
13  * accelerating, and returns the time to wait before sending the next step. A pseudo
14  * usage pattern is as follows:
15  *
16  * <pre>
17  *  float time = 0;
18  *  while (1)
19  *  {
20  *      float delta = ramp_evaluate(&my_ramp, time);
21  *      sleep(delta);
22  *      do_motor_step();
23  *      time += delta;
24  *  }
25  * </pre>
26  *
27  * A similar pattern can be used to decelerate (it is sufficient to move the total
28  * time backward, such as "time -= delta").
29  *
30  * The ramp can be configured with ramp_setup(), providing it with the minimum and
31  * maximum operating frequency of the motor, and the total acceleration time in
32  * milliseconds (that is, the time that will be needed to accelerate from the
33  * minimum frequency to the maximum frequency).
34  *
35  * Both a very precise floating point and a very fast fixed point implementation
36  * of the ramp evaluation are provided. The fixed point is hand-optimized assembly
37  * for DSP56000 (but a portable C version of it can be easily written, see the
38  * comments in the code).
39  *
40  * \version $Id$
41  *
42  * \author Simone Zinanni <s.zinanni@develer.com>
43  * \author Giovanni Bajo <rasky@develer.com>
44  * \author Daniele Basile <asterix@develer.com>
45  *
46  * $WIZ$ module_name = "ramp"
47  * $WIZ$ module_configuration = "bertos/cfg/cfg_ramp.h"
48  */
49
50 #ifndef ALGO_RAMP_H
51 #define ALGO_RAMP_H
52
53 #include "hw/hw_stepper.h"
54
55 #include "cfg/cfg_ramp.h"
56
57 #include <cfg/compiler.h>
58
59
60 /**
61  * Convert microseconds to timer clock ticks
62  */
63 #define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000))
64
65 /**
66  * Convert timer clock ticks back to microseconds
67  */
68 #define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000))
69
70 /**
71  * Convert microseconds to Hz
72  */
73 #define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros)))
74
75 /**
76  * Convert frequency (in Hz) to time (in microseconds)
77  */
78 #define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz)))
79
80 /**
81  * Multiply \p a and \p b two integer at 32 bit and extract the high 16 bit word.
82  */
83 #define FIX_MULT32(a,b)  (((uint64_t)(a)*(uint32_t)(b)) >> 16)
84
85 /**
86  * Structure holding pre-calculated data for speeding up real-time evaluation
87  * of the ramp. This structure is totally different between the fixed and the
88  * floating point version of the code.
89  *
90  * Consult the file-level documentation of ramp.c for more information about
91  * the values of this structure.
92  */
93 struct RampPrecalc
94 {
95 #if RAMP_USE_FLOATING_POINT
96         float beta;
97         float alpha;
98         float gamma;
99 #else
100         uint16_t max_div_min;
101         uint32_t inv_total_time;
102 #endif
103 };
104
105
106 /**
107  * Ramp structure
108  */
109 struct Ramp
110 {
111         uint32_t clocksRamp;
112         uint16_t clocksMinWL;
113         uint16_t clocksMaxWL;
114
115         struct RampPrecalc precalc; ///< pre-calculated values for speed
116 };
117
118
119 /*
120  * Function prototypes
121  */
122 void ramp_compute(
123         struct Ramp * ramp,
124         uint32_t clocksInRamp,
125         uint16_t clocksInMinWavelength,
126         uint16_t clocksInMaxWavelength);
127
128
129 /** Setup an acceleration ramp for a stepper motor
130  *
131  *  \param ramp Ramp to fill
132  *  \param length Length of the ramp (milliseconds)
133  *  \param minFreq Minimum operating frequency of the motor (hertz)
134  *  \param maxFreq Maximum operating frequency of the motor (hertz)
135  *
136  */
137 void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq);
138
139
140 /**
141  * Initialize a new ramp with default values
142  */
143 void ramp_default(struct Ramp *ramp);
144
145
146 /**
147  * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since
148  * the start of the acceleration, compute the next step, that is the interval at which
149  * send the signal to the motor.
150  *
151  * \note The fixed point version does not work when curClock is zero. Anyway,
152  * the first step is always clocksMaxWL, as stored within the ramp structure.
153  */
154 #if RAMP_USE_FLOATING_POINT
155         float ramp_evaluate(const struct Ramp* ramp, float curClock);
156 #else
157         uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock);
158 #endif
159
160
161 /** Self test */
162 int ramp_testSetup(void);
163 int ramp_testRun(void);
164 int ramp_testTearDown(void);
165
166 #endif /* ALGO_RAMP_H */
167