Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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