Update preset.
[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  *
41  * \author Simone Zinanni <s.zinanni@develer.com>
42  * \author Giovanni Bajo <rasky@develer.com>
43  * \author Daniele Basile <asterix@develer.com>
44  *
45  * $WIZ$ module_name = "ramp"
46  * $WIZ$ module_configuration = "bertos/cfg/cfg_ramp.h"
47  */
48
49 #ifndef ALGO_RAMP_H
50 #define ALGO_RAMP_H
51
52 #include "hw/hw_stepper.h"
53
54 #include "cfg/cfg_ramp.h"
55
56 #include <cfg/compiler.h>
57
58
59 /**
60  * Convert microseconds to timer clock ticks
61  */
62 #define TIME2CLOCKS(micros) ((uint32_t)(micros) * (STEPPER_CLOCK / 1000000))
63
64 /**
65  * Convert timer clock ticks back to microseconds
66  */
67 #define CLOCKS2TIME(clocks) ((uint32_t)(clocks) / (STEPPER_CLOCK / 1000000))
68
69 /**
70  * Convert microseconds to Hz
71  */
72 #define MICROS2FREQ(micros) (1000000UL / ((uint32_t)(micros)))
73
74 /**
75  * Convert frequency (in Hz) to time (in microseconds)
76  */
77 #define FREQ2MICROS(hz) (1000000UL / ((uint32_t)(hz)))
78
79 /**
80  * Multiply \p a and \p b two integer at 32 bit and extract the high 16 bit word.
81  */
82 #define FIX_MULT32(a,b)  (((uint64_t)(a)*(uint32_t)(b)) >> 16)
83
84 /**
85  * Structure holding pre-calculated data for speeding up real-time evaluation
86  * of the ramp. This structure is totally different between the fixed and the
87  * floating point version of the code.
88  *
89  * Consult the file-level documentation of ramp.c for more information about
90  * the values of this structure.
91  */
92 struct RampPrecalc
93 {
94 #if RAMP_USE_FLOATING_POINT
95         float beta;
96         float alpha;
97         float gamma;
98 #else
99         uint16_t max_div_min;
100         uint32_t inv_total_time;
101 #endif
102 };
103
104
105 /**
106  * Ramp structure
107  */
108 struct Ramp
109 {
110         uint32_t clocksRamp;
111         uint16_t clocksMinWL;
112         uint16_t clocksMaxWL;
113
114         struct RampPrecalc precalc; ///< pre-calculated values for speed
115 };
116
117
118 /*
119  * Function prototypes
120  */
121 void ramp_compute(
122         struct Ramp * ramp,
123         uint32_t clocksInRamp,
124         uint16_t clocksInMinWavelength,
125         uint16_t clocksInMaxWavelength);
126
127
128 /** Setup an acceleration ramp for a stepper motor
129  *
130  *  \param ramp Ramp to fill
131  *  \param length Length of the ramp (milliseconds)
132  *  \param minFreq Minimum operating frequency of the motor (hertz)
133  *  \param maxFreq Maximum operating frequency of the motor (hertz)
134  *
135  */
136 void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq);
137
138
139 /**
140  * Initialize a new ramp with default values
141  */
142 void ramp_default(struct Ramp *ramp);
143
144
145 /**
146  * Evaluate the ramp at the given point. Given a \a ramp, and the current \a clock since
147  * the start of the acceleration, compute the next step, that is the interval at which
148  * send the signal to the motor.
149  *
150  * \note The fixed point version does not work when curClock is zero. Anyway,
151  * the first step is always clocksMaxWL, as stored within the ramp structure.
152  */
153 #if RAMP_USE_FLOATING_POINT
154         float ramp_evaluate(const struct Ramp* ramp, float curClock);
155 #else
156         uint16_t ramp_evaluate(const struct Ramp* ramp, uint32_t curClock);
157 #endif
158
159
160 /** Self test */
161 int ramp_testSetup(void);
162 int ramp_testRun(void);
163 int ramp_testTearDown(void);
164
165 #endif /* ALGO_RAMP_H */
166