ramp.c

Go to the documentation of this file.
00001 
00105 #include "ramp.h"
00106 #include <cfg/debug.h>
00107 
00108 #include <string.h> // memcpy()
00109 
00113 #define FIX_MULT32(a,b)  (((uint64_t)(a)*(uint32_t)(b)) >> 16)
00114 
00115 void ramp_compute(struct Ramp *ramp, uint32_t clocksRamp, uint16_t clocksMinWL, uint16_t clocksMaxWL)
00116 {
00117     ASSERT(clocksMaxWL >= clocksMinWL);
00118 
00119     // Save values in ramp struct
00120     ramp->clocksRamp = clocksRamp;
00121     ramp->clocksMinWL = clocksMinWL;
00122     ramp->clocksMaxWL = clocksMaxWL;
00123 
00124 #if RAMP_USE_FLOATING_POINT
00125     ramp->precalc.gamma = ramp->clocksMaxWL - ramp->clocksMinWL;
00126     ramp->precalc.beta = (float)ramp->clocksMinWL * (float)ramp->clocksRamp;
00127     ramp->precalc.alpha = ramp->precalc.beta * (float)ramp->clocksMaxWL;
00128 
00129 #else
00130     ramp->precalc.max_div_min = ((uint32_t)clocksMinWL << 16) / (uint32_t)clocksMaxWL;
00131 
00132     /* Calcola 1/total_time in fixed point .32. Assumiamo che la rampa possa al
00133      * massimo avere 25 bit (cioé valore in tick fino a 2^25, che con il
00134      * prescaler=3 sono circa 7 secondi). Inoltre, togliamo qualche bit di precisione
00135      * da destra (secondo quanto specificato in RAMP_CLOCK_SHIFT_PRECISION).
00136      */
00137     ASSERT(ramp->clocksRamp < (1UL << (24 + RAMP_CLOCK_SHIFT_PRECISION)));
00138     ramp->precalc.inv_total_time = 0xFFFFFFFFUL / (ramp->clocksRamp >> RAMP_CLOCK_SHIFT_PRECISION);
00139     ASSERT(ramp->precalc.inv_total_time < 0x1000000UL);
00140 
00141 #endif
00142 }
00143 
00144 
00145 void ramp_setup(struct Ramp* ramp, uint32_t length, uint32_t minFreq, uint32_t maxFreq)
00146 {
00147     uint32_t minWL, maxWL;
00148 
00149     minWL = TIME2CLOCKS(FREQ2MICROS(maxFreq));
00150     maxWL = TIME2CLOCKS(FREQ2MICROS(minFreq));
00151 
00152     ASSERT2(minWL < 65536UL, "Maximum frequency too high");
00153     ASSERT2(maxWL < 65536UL, "Minimum frequency too high");
00154     ASSERT(maxFreq > minFreq);
00155 
00156     ramp_compute(
00157         ramp,
00158         TIME2CLOCKS(length),
00159         TIME2CLOCKS(FREQ2MICROS(maxFreq)),
00160         TIME2CLOCKS(FREQ2MICROS(minFreq))
00161     );
00162 }
00163 
00164 void ramp_default(struct Ramp *ramp)
00165 {
00166     ramp_setup(ramp, RAMP_DEF_TIME, RAMP_DEF_MINFREQ, RAMP_DEF_MAXFREQ);
00167 }
00168 
00169 #if RAMP_USE_FLOATING_POINT
00170 
00171 float ramp_evaluate(const struct Ramp* ramp, float curClock)
00172 {
00173     return ramp->precalc.alpha / (curClock * ramp->precalc.gamma + ramp->precalc.beta);
00174 }
00175 
00176 #else
00177 
00178 INLINE uint32_t fix_mult32(uint32_t m1, uint32_t m2)
00179 {
00180     uint32_t accum = 0;
00181     accum += m1 * ((m2 >> 0) & 0xFF);
00182     accum >>= 8;
00183     accum += m1 * ((m2 >> 8) & 0xFF);
00184     accum >>= 8;
00185     accum += m1 * ((m2 >> 16) & 0xFF);
00186     return accum;
00187 }
00188 
00189 //   a*b >> 16
00190 INLINE uint16_t fix_mult16(uint16_t a, uint32_t b)
00191 {
00192     return (b*(uint32_t)a) >> 16;
00193 }
00194 
00195 uint16_t FAST_FUNC ramp_evaluate(const struct Ramp* ramp, uint32_t curClock)
00196 {
00197     uint16_t t = FIX_MULT32(curClock >> RAMP_CLOCK_SHIFT_PRECISION, ramp->precalc.inv_total_time);
00198     uint16_t denom =  fix_mult16((uint16_t)~t + 1, ramp->precalc.max_div_min) + t;
00199     uint16_t cur_delta = ((uint32_t)ramp->clocksMinWL << 16) / denom;
00200 
00201     return cur_delta;
00202 }
00203 
00204 #endif
00205 
00206