-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsin1.cpp
96 lines (88 loc) · 2.9 KB
/
sin1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//
// Created by Richard on 12.05.2020.
//
/**
* Example for a sine/cosine table lookup
* Implementation of sin1() / cos1().
* We "outsource" this implementation so that the precompiler constants/macros
* are only defined here.
*
* @file sin1.c
* @author stfwi
**/
#include "sin1.h"
/*
* The number of bits of our data type: here 16 (sizeof operator returns bytes).
*/
#define INT16_BITS (8 * sizeof(int16_t))
#ifndef INT16_MAX
#define INT16_MAX ((1<<(INT16_BITS-1))-1)
#endif
/*
* "5 bit" large table = 32 values. The mask: all bit belonging to the table
* are 1, the all above 0.
*/
#define TABLE_BITS (5)
#define TABLE_SIZE (1<<TABLE_BITS)
#define TABLE_MASK (TABLE_SIZE-1)
/*
* The lookup table is to 90DEG, the input can be -360 to 360 DEG, where negative
* values are transformed to positive before further processing. We need two
* additional bits (*4) to represent 360 DEG:
*/
#define LOOKUP_BITS (TABLE_BITS+2)
#define LOOKUP_MASK ((1<<LOOKUP_BITS)-1)
#define FLIP_BIT (1<<TABLE_BITS)
#define NEGATE_BIT (1<<(TABLE_BITS+1))
#define INTERP_BITS (INT16_BITS-1-LOOKUP_BITS)
#define INTERP_MASK ((1<<INTERP_BITS)-1)
/**
* "5 bit" lookup table for the offsets. These are the sines for exactly
* at 0deg, 11.25deg, 22.5deg etc. The values are from -1 to 1 in Q15.
*/
static int16_t sin90[TABLE_SIZE+1] = {
0x0000,0x0647,0x0c8b,0x12c7,0x18f8,0x1f19,0x2527,0x2b1e,
0x30fb,0x36b9,0x3c56,0x41cd,0x471c,0x4c3f,0x5133,0x55f4,
0x5a81,0x5ed6,0x62f1,0x66ce,0x6a6c,0x6dc9,0x70e1,0x73b5,
0x7640,0x7883,0x7a7c,0x7c29,0x7d89,0x7e9c,0x7f61,0x7fd7,
0x7fff
};
/**
* Sine calculation using interpolated table lookup.
* Instead of radiants or degrees we use "turns" here. Means this
* sine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
*
* See the full description at www.AtWillys.de for the detailed
* explanation.
*
* @param int16_t angle Q15
* @return int16_t Q15
*/
int16_t sin1(int16_t angle)
{
int16_t v0, v1;
if(angle < 0) { angle += INT16_MAX; angle += 1; }
v0 = (angle >> INTERP_BITS);
if(v0 & FLIP_BIT) { v0 = ~v0; v1 = ~angle; } else { v1 = angle; }
v0 &= TABLE_MASK;
v1 = sin90[v0] + (int16_t) (((int32_t) (sin90[v0+1]-sin90[v0]) * (v1 & INTERP_MASK)) >> INTERP_BITS);
if((angle >> INTERP_BITS) & NEGATE_BIT) v1 = -v1;
return v1;
}
/**
* Cosine calculation using interpolated table lookup.
* Instead of radiants or degrees we use "turns" here. Means this
* cosine does NOT return one phase for 0 to 2*PI, but for 0 to 1.
* Input: -1 to 1 as int16 Q15 == -32768 to 32767.
* Output: -1 to 1 as int16 Q15 == -32768 to 32767.
*
* @param int16_t angle Q15
* @return int16_t Q15
*/
int16_t cos1(int16_t angle)
{
if(angle < 0) { angle += INT16_MAX; angle += 1; }
return sin1(angle - (int16_t)(((int32_t)INT16_MAX * 270) / 360));
}