Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1920 - 1
/****************************************************************/
2
/*                                                                                                                                                                                                                                                      */
3
/*                                                                       NG-Video 5,8GHz                                                                                                                */
4
/*                                                                                                                                                                                                                                                      */
5
/*                                                      Copyright (C) 2011 - gebad                                                                                      */
6
/*                                                                                                                                                                                                                                                      */
7
/*      This code is distributed under the GNU Public License                           */
8
/*      which can be found at http://www.gnu.org/licenses/gpl.txt               */
9
/*                                                                                                                                                                                                                                                      */
10
/****************************************************************/
11
 
12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <math.h>
15
#include <avr/pgmspace.h>
16
 
17
#include "mymath.h"
18
 
19
// http://www.mikrocontroller.net/articles/AVR_Arithmetik#avr-gcc_Implementierung_.2832_Bit.29
20
unsigned int sqrt32(uint32_t q)
21
{       uint16_t r, mask;
22
        uint16_t i = 8*sizeof (r) -1;
23
 
24
        r = mask = 1 << i;
25
        for (; i > 0; i--) {
26
                mask >>= 1;
27
 
28
                if (q < (uint32_t) r*r)
29
                        r -= mask;
30
                else
31
                        r += mask;
32
        }
33
 
34
        if (q < (uint32_t) r*r)
35
                r -= 1;
36
 
37
        return r;
38
}
39
 
40
// aus Orginal MK source code
41
// sinus with argument in degree at an angular resolution of 1 degree and a discretisation of 13 bit.
42
const uint16_t sinlookup[91] = {0, 143, 286, 429, 571, 714, 856, 998, 1140, 1282, 1423, 1563, 1703, \
43
                                                                                                                                1843, 1982, 2120, 2258, 2395, 2531, 2667, 2802, 2936, 3069, 3201, 3332, \
44
                                                                                                                                3462, 3591, 3719, 3846, 3972, 4096, 4219, 4341, 4462, 4581, 4699, 4815, \
45
                                                                                                                                4930, 5043, 5155, 5266, 5374, 5482, 5587, 5691, 5793, 5893, 5991, 6088, \
46
                                                                                                                                6183, 6275, 6366, 6455, 6542, 6627, 6710, 6791, 6870, 6947, 7022, 7094, \
47
                                                                                                                                7165, 7233, 7299, 7363, 7424, 7484, 7541, 7595, 7648, 7698, 7746, 7791, \
48
                                                                                                                                7834, 7875, 7913, 7949, 7982, 8013, 8041, 8068, 8091, 8112, 8131, 8147, \
49
                                                                                                                                8161, 8172, 8181, 8187, 8191, 8192};
50
 
51
//double c_cos_8192(int16_t angle)
52
int16_t c_cos_8192(int16_t angle)
53
{
54
        int8_t m,n;
55
        int16_t sinus;
56
 
57
        angle = 90 - angle;
58
        // avoid negative angles
59
        if (angle < 0)
60
        {
61
                m = -1;
62
                angle = -angle;
63
        }
64
        else m = +1;
65
 
66
        // fold angle to interval 0 to 359
67
        angle %= 360;
68
 
69
        // check quadrant
70
        if (angle <= 90) n = 1; // first quadrant
71
        else if ((angle > 90) && (angle <= 180)) {angle = 180 - angle; n = 1;}          // second quadrant
72
        else if ((angle > 180) && (angle <= 270)) {angle = angle - 180; n = -1;}        // third quadrant
73
        else {angle = 360 - angle; n = -1;}     //fourth quadrant
74
        // get lookup value
75
        sinus = sinlookup[angle];
76
        // calculate sinus value
77
        return (sinus * m * n);
78
}
79
 
80
/* ----------------------------------------------------------------------------------------------
81
 
82
  atan2.S
83
 
84
  Author:   Reiner Patommel
85
 
86
atan2.S uses CORDIC, an algorithm which was developed in 1956 by Jack Volder.
87
CORDIC can be used to calculate trigonometric, hyperbolic and linear
88
functions and is until today implemented in most pocket calculators.
89
The algorithm makes only use of simple integer arithmetic.
90
 
91
The CORDIC equations in vectoring mode for trigonometric functions are:
92
Xi+1 = Xi - Si * (Yi * 1 / 2^i)
93
Yi+1 = Yi + Si * (Xi * 1 / 2^i)
94
Zi+1 = Zi - Si *  atan(1 / 2^i)
95
where Si = +1 if Yi < 0 else Si = -1
96
The rotation angles are limited to -PI/2 and PI/2 i.e.
97
-90 degrees ... +90 degrees
98
 
99
For the calculation of atan2(x,y) we need a small pre-calculated table of
100
angles or radians with the values Tn = atan(1/2^i).
101
We rotate the vector(Xo,Yo) in steps to the x-axis i.e. we drive Y to 0 and
102
accumulate the rotated angles or radians in Z.  The direction of the rotation
103
will be positive or negative depending on the sign of Y after the previous
104
rotation and the rotation angle will decrease from step to step. (The first
105
step is 45 degrees, the last step is 0.002036 degrees for n = 15).
106
 
107
After n rotations the variables will have the following values:
108
Yn      = ideally 0
109
Xn      = c*sqrt(Xo^2+Yo^2)                     (magnitude of the vector)
110
Zn      = Zo+atan(Yo/Xo)                        (accumulated rotation angles or radians)
111
 
112
c, the cordic gain, is the product Pn of sqrt(1+2^(-2i)) and amounts to
113
approx. 1.64676 for n = 15.
114
 
115
In order to represent X, Y and Z as integers we introduce a scaling factor Q
116
which is chosen as follows:
117
1.      We normalize Xo and Yo (starting values) to be less than or equal to 1*Q and
118
        set Zo = 0 i.e. Xomax = 1*Q, Yomax = 1*Q, Zo = 0.
119
2.      With Xo = 1*Q and Yo = 1*Q, Xn will be Xnmax = Q*c*sqrt(2) = 2.329*Q
120
3.      In order to boost accuracy we only cover the rotation angles between 0 and PI/2
121
        i.e. X and Z are always > 0 and therefore can be unsigned.
122
        (We do the quadrant correction afterwards based on the initial signs of x and y)
123
4.      If X is an unsigned int, Xnmax = 65536, and Q = 65536/2.329 = 28140.
124
        i.e.
125
        Xnmax = 65536                                   --> unsigned int
126
        Ynmax = +/- 28140                               --> signed int
127
        Znmax = PI/2 * 28140 = 44202    --> unsigned int
128
        The systematic error is 90/44202 = 0.002036 degrees or 0.0000355 rad.
129
 
130
Below is atan2 and atan in C: */
131
 
132
#define getAtanVal(x)                   (uint16_t)pgm_read_word(&atantab[x])
133
 
134
uint16_t atantab[T] PROGMEM = {22101,13047,6894,3499,1756,879,440,220,110,55,27,14,7,3,2,1};
135
 
136
int16_t my_atan2(int32_t y, int32_t x)
137
{       unsigned char i;
138
        uint32_t xQ;
139
        int32_t yQ;
140
        uint32_t angle = 0;
141
        uint32_t tmp;
142
        double x1, y1;
143
 
144
        x1 = abs(x);
145
        y1 = abs(y);
146
 
147
        if (y1 == 0) {
148
                if (x < 0)
149
                        return (180);
150
                else
151
                        return 0;
152
        }
153
 
154
        if (x1 < y1) {
155
                x1 /= y1;
156
                y1 = 1;
157
        }
158
        else {
159
                y1 /= x1;
160
                x1 = 1;
161
        }
162
 
163
        xQ = SCALED(x1);
164
        yQ = SCALED(y1);
165
 
166
        for (i = 0; i < T-1; i++) {
167
                tmp = xQ >> i;
168
                if (yQ < 0) {
169
                        xQ -= yQ >> i;
170
                        yQ += tmp;
171
                        angle -= getAtanVal(i);
172
                }
173
                else {
174
                        xQ += yQ >> i;
175
                        yQ -= tmp;
176
                        angle += getAtanVal(i);
177
                }
178
        }
179
 
180
        angle = RAD_TO_DEG * angle/Q;
181
        if (x <= 0)
182
                angle = 180 - angle;
183
        if (y <= 0)
184
                return(-angle);
185
        return(angle);
186
}
187