Skip to content

Commit 285795e

Browse files
committed
Added specializations to Line for U/SFix
1 parent 3784ade commit 285795e

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

Line.h

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "WProgram.h"
1919
#endif
2020

21+
#include<FixMath.h>
22+
2123
/** For linear changes with a minimum of calculation at each step. For instance,
2224
you can use Line to make an oscillator glide from one frequency to another,
2325
pre-calculating the required phase increments for each end and then letting your
@@ -33,6 +35,9 @@ represent fractional numbers. Google "fixed point arithmetic" if this is new to
3335
you.
3436
*/
3537

38+
39+
40+
3641
template <class T>
3742
class Line
3843
{
@@ -315,6 +320,174 @@ class Line <unsigned long>
315320
}
316321
};
317322

323+
324+
/* UFix specialisation */
325+
template<int8_t NI, int8_t NF>
326+
class Line<UFix<NI, NF>>
327+
{
328+
private:
329+
typedef UFix<NI, NF> internal_type;
330+
internal_type current_value;
331+
internal_type step_size;
332+
333+
public:
334+
/** Constructor. Use the template parameter to set the type of numbers you
335+
want to use. For example, Line \<int\> myline; makes a Line which uses ints.
336+
*/
337+
Line (){;}
338+
339+
/** Increments one step along the line.
340+
@return the next value.
341+
*/
342+
inline
343+
internal_type next()
344+
{
345+
current_value = current_value + step_size;
346+
return current_value;
347+
}
348+
349+
/** Set the current value of the line.
350+
The Line will continue incrementing from this
351+
value using any previously calculated step size.
352+
@param value the number to set the Line's current_value to.
353+
*/
354+
inline
355+
void set(internal_type value)
356+
{
357+
current_value=value;
358+
}
359+
360+
/** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
361+
@param targetvalue the value to move towards.
362+
@param num_steps how many steps to take to reach the target as a UFix<_NI,0>
363+
*/
364+
template<int8_t _NI>
365+
void set(internal_type targetvalue, UFix<_NI,0> num_steps)
366+
{
367+
if(num_steps.asRaw()) {
368+
internal_type numerator = targetvalue-current_value;
369+
step_size = numerator*num_steps.invAccurate();
370+
} else {
371+
step_size = 0;
372+
current_value = targetvalue;
373+
}
374+
}
375+
376+
377+
/** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
378+
@param targetvalue the value to move towards.
379+
@param num_steps how many steps to take to reach the target.
380+
*/
381+
template<typename T>
382+
void set(internal_type targetvalue, T num_steps)
383+
{
384+
if(num_steps) {
385+
internal_type numerator = targetvalue-current_value;
386+
step_size = internal_type(numerator.asRaw()/num_steps,true);
387+
} else {
388+
step_size = 0;
389+
current_value = targetvalue;
390+
}
391+
}
392+
393+
/** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
394+
@param startvalue the number to set the Line's current_value to.
395+
@param targetvalue the value to move towards.
396+
@param num_steps how many steps to take to reach the target.
397+
*/
398+
template<typename T>
399+
void set(internal_type startvalue, internal_type targetvalue, T num_steps)
400+
{
401+
set(startvalue);
402+
set(targetvalue, num_steps);
403+
}
404+
};
405+
406+
407+
/* SFix specialisation (if someone has an idea to avoid duplication with UFix) */
408+
template<int8_t NI, int8_t NF>
409+
class Line<SFix<NI, NF>>
410+
{
411+
private:
412+
typedef SFix<NI, NF> internal_type;
413+
internal_type current_value;
414+
internal_type step_size;
415+
416+
public:
417+
/** Constructor. Use the template parameter to set the type of numbers you
418+
want to use. For example, Line \<int\> myline; makes a Line which uses ints.
419+
*/
420+
Line (){;}
421+
422+
/** Increments one step along the line.
423+
@return the next value.
424+
*/
425+
inline
426+
internal_type next()
427+
{
428+
current_value = current_value + step_size;
429+
return current_value;
430+
}
431+
432+
/** Set the current value of the line.
433+
The Line will continue incrementing from this
434+
value using any previously calculated step size.
435+
@param value the number to set the Line's current_value to.
436+
*/
437+
inline
438+
void set(internal_type value)
439+
{
440+
current_value=value;
441+
}
442+
443+
/** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
444+
@param targetvalue the value to move towards.
445+
@param num_steps how many steps to take to reach the target as a UFix<_NI,0>
446+
*/
447+
template<int8_t _NI>
448+
void set(internal_type targetvalue, UFix<_NI,0> num_steps)
449+
{
450+
if(num_steps.asRaw()) {
451+
internal_type numerator = targetvalue-current_value;
452+
step_size = numerator*num_steps.invAccurate();
453+
} else {
454+
step_size = 0;
455+
current_value = targetvalue;
456+
}
457+
}
458+
459+
460+
/** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
461+
@param targetvalue the value to move towards.
462+
@param num_steps how many steps to take to reach the target.
463+
*/
464+
template<typename T>
465+
void set(internal_type targetvalue, T num_steps)
466+
{
467+
if(num_steps) {
468+
internal_type numerator = targetvalue-current_value;
469+
step_size = internal_type(numerator.asRaw()/num_steps,true);
470+
} else {
471+
step_size = 0;
472+
current_value = targetvalue;
473+
}
474+
}
475+
476+
/** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
477+
@param startvalue the number to set the Line's current_value to.
478+
@param targetvalue the value to move towards.
479+
@param num_steps how many steps to take to reach the target.
480+
*/
481+
template<typename T>
482+
void set(internal_type startvalue, internal_type targetvalue, T num_steps)
483+
{
484+
set(startvalue);
485+
set(targetvalue, num_steps);
486+
}
487+
};
488+
489+
490+
318491
/**
319492
@example 02.Control/Control_Tremelo/Control_Tremelo.ino
320493
This example demonstrates the Line class.

0 commit comments

Comments
 (0)