2020-11-08 09:48:03 +00:00
// Sine Generator functions using only multiplication, addition and bit shifting
2018-02-19 07:29:47 +00:00
// Uses a single division for converting the wavelength to a reciprocal.
2020-11-08 09:48:03 +00:00
// Generates sine using the series sin(x) = x - x^/3! + x^-5! - x^7/7! ...
2018-02-18 14:35:17 +00:00
// Uses the approximation sin(x) = x - x^/6 + x^/128
2020-11-08 09:48:03 +00:00
// Optimization possibility: Use symmetries when generating sine tables. wavelength%2==0 -> mirror symmetry over PI, wavelength%4==0 -> mirror symmetry over PI/2.
2018-02-18 14:35:17 +00:00
2020-11-08 09:48:03 +00:00
# include <sine.h>
2020-04-11 19:15:34 +00:00
# include <division.h>
# include <multiply.h>
2018-02-18 14:35:17 +00:00
2018-02-20 09:53:31 +00:00
// PI*2 in u[4.28] format
2024-01-02 18:45:16 +00:00
const unsigned long PI2_u4f28 = 0x6487ed51 ;
2018-02-20 09:53:31 +00:00
// PI in u[4.28] format
2024-01-02 18:45:16 +00:00
const unsigned long PI_u4f28 = 0x3243f6a9 ;
2018-02-20 09:53:31 +00:00
// PI/2 in u[4.28] format
2024-01-02 18:45:16 +00:00
const unsigned long PI_HALF_u4f28 = 0x1921FB54 ;
2018-02-20 09:53:31 +00:00
2018-02-23 21:15:10 +00:00
// PI*2 in u[4.12] format
2024-01-02 18:45:16 +00:00
const unsigned int PI2_u4f12 = 0x6488 ;
2018-02-23 21:15:10 +00:00
// PI in u[4.12] format
2024-01-02 18:45:16 +00:00
const unsigned int PI_u4f12 = 0x3244 ;
2018-02-23 21:15:10 +00:00
// PI/2 in u[4.12] format
2024-01-02 18:45:16 +00:00
const unsigned int PI_HALF_u4f12 = 0x1922 ;
2018-02-23 21:15:10 +00:00
2020-11-08 09:48:03 +00:00
// Generate signed (large) unsigned int sine table - on the full -$7fff - $7fff range
2018-02-18 14:35:17 +00:00
// sintab - the table to generate into
2020-11-08 09:48:03 +00:00
// wavelength - the number of sine points in a total sine wavelength (the size of the table)
2020-04-13 18:00:13 +00:00
void sin16s_gen ( signed int * sintab , unsigned int wavelength ) {
2018-02-23 23:46:25 +00:00
// u[4.28] step = PI*2/wavelength
2020-04-13 18:00:13 +00:00
unsigned long step = div32u16u ( PI2_u4f28 , wavelength ) ; // u[4.28]
2018-02-23 23:46:25 +00:00
// Iterate over the table
2020-04-13 18:00:13 +00:00
unsigned long x = 0 ; // u[4.28]
for ( unsigned int i = 0 ; i < wavelength ; i + + ) {
2019-04-19 08:50:15 +00:00
* sintab + + = sin16s ( x ) ;
2018-02-23 23:46:25 +00:00
x = x + step ;
}
}
2020-11-08 09:48:03 +00:00
// Generate signed int sine table - with values in the range min-max.
2018-07-09 16:39:01 +00:00
// sintab - the table to generate into
2020-11-08 09:48:03 +00:00
// wavelength - the number of sine points in a total sine wavelength (the size of the table)
2020-04-13 18:00:13 +00:00
void sin16s_gen2 ( signed int * sintab , unsigned int wavelength , signed int min , signed int max ) {
signed int ampl = max - min ;
signed int offs = min + ampl > > 1 ; // ampl is always positive so shifting left does not alter the sign
2018-07-09 16:39:01 +00:00
// u[4.28] step = PI*2/wavelength
2020-04-13 18:00:13 +00:00
unsigned long step = div32u16u ( PI2_u4f28 , wavelength ) ; // u[4.28]
2018-07-09 16:39:01 +00:00
// Iterate over the table
2020-04-13 18:00:13 +00:00
unsigned long x = 0 ; // u[4.28]
for ( unsigned int i = 0 ; i < wavelength ; i + + ) {
2021-06-12 18:57:35 +00:00
* sintab + + = offs + ( signed int ) WORD1 ( mul16s ( sin16s ( x ) , ampl ) ) ; // The signed sin() has values [-7fff;7fff] = [-1/2 ; 1/2], so ampl*sin has the right amplitude
2018-07-09 16:39:01 +00:00
x = x + step ;
}
}
2020-11-08 09:48:03 +00:00
// Generate signed char sine table - on the full -$7f - $7f range
2018-02-25 10:10:50 +00:00
// sintab - the table to generate into
2020-11-08 09:48:03 +00:00
// wavelength - the number of sine points in a total sine wavelength (the size of the table)
2020-04-13 18:00:13 +00:00
void sin8s_gen ( signed char * sintab , unsigned int wavelength ) {
2018-02-25 10:10:50 +00:00
// u[4.28] step = PI*2/wavelength
2020-04-13 18:00:13 +00:00
unsigned int step = div16u ( PI2_u4f12 , wavelength ) ; // u[4.12]
2018-02-25 10:10:50 +00:00
// Iterate over the table
2020-04-13 18:00:13 +00:00
unsigned int x = 0 ; // u[4.12]
for ( unsigned int i = 0 ; i < wavelength ; i + + ) {
2018-02-25 10:10:50 +00:00
* sintab + + = sin8s ( x ) ;
x = x + step ;
}
}
2020-11-08 09:48:03 +00:00
// Calculate signed int sine sin(x)
2020-04-13 18:00:13 +00:00
// x: unsigned long input u[4.28] in the interval $00000000 - PI2_u4f28
// result: signed int sin(x) s[0.15] - using the full range -$7fff - $7fff
signed int sin16s ( unsigned long x ) {
2020-11-08 09:48:03 +00:00
// Move x1 into the range 0-PI/2 using sine mirror symmetries
2020-04-13 18:00:13 +00:00
char isUpper = 0 ;
2018-02-24 12:02:15 +00:00
if ( x > = PI_u4f28 ) {
x = x - PI_u4f28 ;
isUpper = 1 ;
}
if ( x > = PI_HALF_u4f28 ) {
x = PI_u4f28 - x ;
}
2018-02-25 10:10:50 +00:00
// sinx = x - x^3/6 + x5/128;
2021-06-12 19:08:42 +00:00
unsigned int x1 = WORD1 ( x < < 3 ) ; // u[1.15]
2020-04-13 18:00:13 +00:00
unsigned int x2 = mulu16_sel ( x1 , x1 , 0 ) ; // u[2.14] x^2
unsigned int x3 = mulu16_sel ( x2 , x1 , 1 ) ; // u[2.14] x^3
2024-01-02 18:45:16 +00:00
unsigned int x3_6 = mulu16_sel ( x3 , 0x10000 / 6 , 1 ) ; // u[1.15] x^3/6;
2020-04-13 18:00:13 +00:00
unsigned int usinx = x1 - x3_6 ; // u[1.15] x - x^3/6
unsigned int x4 = mulu16_sel ( x3 , x1 , 0 ) ; // u[3.13] x^4
unsigned int x5 = mulu16_sel ( x4 , x1 , 0 ) ; // u[4.12] x^5
unsigned int x5_128 = x5 > > 4 ; // // u[1.15] x^5/128 -- much more efficient than mul_u16_sel(x5, $10000/128, 3);
2018-02-24 23:39:19 +00:00
usinx = usinx + x5_128 ; // u[1.15] (first bit is always zero)
2020-04-13 18:00:13 +00:00
signed int sinx = ( signed int ) usinx ; // s[0.15]
2018-02-24 12:02:15 +00:00
if ( isUpper ! = 0 ) {
2020-04-13 18:00:13 +00:00
sinx = - ( signed int ) usinx ; // s[0.15];
2018-02-24 12:02:15 +00:00
}
return sinx ;
}
2020-11-08 09:48:03 +00:00
// Calculate signed char sine sin(x)
2020-04-13 18:00:13 +00:00
// x: unsigned int input u[4.12] in the interval $0000 - PI2_u4f12
// result: signed char sin(x) s[0.7] - using the full range -$7f - $7f
signed char sin8s ( unsigned int x ) {
2020-11-08 09:48:03 +00:00
// Move x1 into the range 0-PI/2 using sine mirror symmetries
2020-04-13 18:00:13 +00:00
char isUpper = 0 ;
2018-02-25 10:10:50 +00:00
if ( x > = PI_u4f12 ) {
x = x - PI_u4f12 ;
isUpper = 1 ;
}
if ( x > = PI_HALF_u4f12 ) {
x = PI_u4f12 - x ;
}
// sinx = x - x^3/6 + x5/128;
2021-06-14 06:51:55 +00:00
char x1 = BYTE1 ( x < < 3 ) ; // u[1.7]
2020-04-13 18:00:13 +00:00
char x2 = mulu8_sel ( x1 , x1 , 0 ) ; // u[2.6] x^2
char x3 = mulu8_sel ( x2 , x1 , 1 ) ; // u[2.6] x^3
2024-01-02 18:45:16 +00:00
const char DIV_6 = 0x2b ; // u[0.7] - $2a.aa rounded to $2b
2020-04-13 18:00:13 +00:00
char x3_6 = mulu8_sel ( x3 , DIV_6 , 1 ) ; // u[1.7] x^3/6;
char usinx = x1 - x3_6 ; // u[1.7] x - x^3/6
char x4 = mulu8_sel ( x3 , x1 , 0 ) ; // u[3.5] x^4
char x5 = mulu8_sel ( x4 , x1 , 0 ) ; // u[4.4] x^5
char x5_128 = x5 > > 4 ; // // u[1.7] x^5/128 -- much more efficient than mul_u16_sel(x5, $10000/128, 3);
2018-02-25 10:10:50 +00:00
usinx = usinx + x5_128 ; // u[1.7] (first bit is always zero)
2018-02-25 13:07:44 +00:00
if ( usinx > = 128 ) { usinx - - ; } // rounding may occasionally result in $80 - lower into range ($00-$7f)
2020-04-13 18:00:13 +00:00
signed char sinx = ( signed char ) usinx ; // s[0.7]
2018-02-25 10:10:50 +00:00
if ( isUpper ! = 0 ) {
2020-04-13 18:00:13 +00:00
sinx = - ( signed char ) usinx ; // s[0.7];
2018-02-25 13:07:44 +00:00
}
return sinx ;
2018-02-25 10:10:50 +00:00
}
2020-04-13 18:00:13 +00:00
// Calculate val*val for two unsigned int values - the result is 16 selected bits of the 32-bit result.
2018-02-23 23:46:25 +00:00
// The select parameter indicates how many of the highest bits of the 32-bit result to skip
2020-04-13 18:00:13 +00:00
unsigned int mulu16_sel ( unsigned int v1 , unsigned int v2 , char select ) {
2021-06-12 18:57:35 +00:00
return WORD1 ( mul16u ( v1 , v2 ) < < select ) ;
2018-02-23 23:46:25 +00:00
}
2020-04-13 18:00:13 +00:00
// Calculate val*val for two unsigned char values - the result is 8 selected bits of the 16-bit result.
2018-02-25 10:10:50 +00:00
// The select parameter indicates how many of the highest bits of the 16-bit result to skip
2020-04-13 18:00:13 +00:00
char mulu8_sel ( char v1 , char v2 , char select ) {
2021-06-12 18:57:35 +00:00
return BYTE1 ( mul8u ( v1 , v2 ) < < select ) ;
2018-02-25 10:10:50 +00:00
}