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