I want to generate a sine signal on an ARM Cortex M0 microcontroller that is customizable concerning its shape by a shape parameter n. Have a look at the plot below as an example. Here I modelled the different curves with the function
$y(x) = (1/2*(1 + sin(x)))^n$
For a higher n, the maxima are "shorter" and the minima are "wider
". For a lower n, the maxima are "wider
" and the minima are "shorter
".
In order to reduce memory consumption and increase performance, I only use integer math to generate the sine signal.
Here's the code for the sine calculation:
Input range [0R 2πR] mapped to [0 to 1024].
Output range [-1.0 1.0] mapped to [-16,384 16,384].
int_fast16_t sin_bam(int angle_bam) {
angle_bam %= 1024;
if (angle_bam < 0)
angle_bam += 1024;
uint_fast16_t sub_angle = angle_bam % (1024u / 2);
int_fast16_t sn = unsigned_mult16x16_into_32(sub_angle, (1024/2 - sub_angle)) / 4;
if (angle_bam & 512) {
sn = -sn;
}
return sn;
}
Does anyone have an idea how to realize such a shape modification only with integer math?
Does anyone have an idea how to realize such a shape modification only with integer math?
n
could also have a range of 1 to 10 for example$y(x) = (1/2*(1 + sin(x)))^n$
OP has a sine approximation function sin_bam()
and then uses that to form 1/2*(1 + sin(x))
which is the hacovercosin(θ). All that is left is a scale power function.
#include <inttypes.h>
#define SCALE 16384
int pow_scale(int x, unsigned n) {
unsigned y = SCALE;
while (n>0) {
if (n%2) {
y = unsigned_mult16x16_into_32(x,y)/SCALE; // 16-bit x 16-bit --> 32-bit product.
}
n /= 2;
x = unsigned_mult16x16_into_32(x,x)/SCALE;
}
return x;
}
// x is the angle in 1024 BAM per period
// output is scaled to range [0....SCALE]
int shaped(int x, unsigned n) {
return pow_scale(SCALE/2 + sin_bam(x)/2), n);
}