Subversion Repositories Projects

Rev

Rev 2147 | Go to most recent revision | Details | Compare with Previous | 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.
2212 - 51
const int16_t sinlookup[91] = {    0,  143,  286,  429,  571,  714,  856,  998, 1140, 1282, 1423, 1563, 1703,     \
2136 - 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
 
2212 - 60
 
2136 - 61
int16_t c_cos_8192(int16_t angle)
62
{
2212 - 63
        return (c_sin_8192(90 - angle));
64
}
65
 
66
 
67
 
68
int16_t c_sin_8192(int16_t angle)
69
{
70
        int8_t m, n;
2136 - 71
        int16_t sinus;
72
 
73
        // avoid negative angles
74
        if (angle < 0)
75
        {
2212 - 76
                        m = -1;
77
                        angle = -angle;
2136 - 78
        }
79
        else m = +1;
80
 
81
        // fold angle to interval 0 to 359
82
        angle %= 360;
83
 
84
        // check quadrant
85
        if (angle <= 90) n = 1; // first quadrant
2212 - 86
        else if ((angle > 90) && (angle <= 180)) {angle = 180 - angle; n = 1;} // second quadrant
87
        else if ((angle > 180) && (angle <= 270)) {angle = angle - 180; n = -1;} // third quadrant
88
        else {angle = 360 - angle; n = -1;}     //fourth quadrant
2136 - 89
        // get lookup value
90
        sinus = sinlookup[angle];
91
        // calculate sinus value
92
        return (sinus * m * n);
93
}
94
 
95
// ----------------------------------------------------------------------------------------------
96
 
97
 
98
const int16_t arccos64[65] = {90,89,88,87,86, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76,
99
                          75, 74, 73, 72, 71, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62,
100
                          61, 60, 59, 58, 57, 56, 55, 54, 53, 51, 50, 49, 48, 47, 45,
101
                          44, 43, 41, 40, 39, 37, 36, 34, 32, 31, 29, 27, 25, 23, 20,
102
                          18, 14, 10, 0};
103
 
104
 
105
 
106
int16_t c_arccos2(int32_t a, int32_t b)
107
{
108
        if(a>b) return(0);
109
        return(arccos64[64 * a / b]);
110
}
111
 
112
 
113
/* ----------------------------------------------------------------------------------------------
114
 
115
  atan2.S
116
 
117
  Author:   Reiner Patommel
118
 
119
atan2.S uses CORDIC, an algorithm which was developed in 1956 by Jack Volder.
120
CORDIC can be used to calculate trigonometric, hyperbolic and linear
121
functions and is until today implemented in most pocket calculators.
122
The algorithm makes only use of simple integer arithmetic.
123
 
124
The CORDIC equations in vectoring mode for trigonometric functions are:
125
Xi+1 = Xi - Si * (Yi * 1 / 2^i)
126
Yi+1 = Yi + Si * (Xi * 1 / 2^i)
127
Zi+1 = Zi - Si *  atan(1 / 2^i)
128
where Si = +1 if Yi < 0 else Si = -1
129
The rotation angles are limited to -PI/2 and PI/2 i.e.
130
-90 degrees ... +90 degrees
131
 
132
For the calculation of atan2(x,y) we need a small pre-calculated table of
133
angles or radians with the values Tn = atan(1/2^i).
134
We rotate the vector(Xo,Yo) in steps to the x-axis i.e. we drive Y to 0 and
135
accumulate the rotated angles or radians in Z.  The direction of the rotation
136
will be positive or negative depending on the sign of Y after the previous
137
rotation and the rotation angle will decrease from step to step. (The first
138
step is 45 degrees, the last step is 0.002036 degrees for n = 15).
139
 
140
After n rotations the variables will have the following values:
141
Yn      = ideally 0
142
Xn      = c*sqrt(Xo^2+Yo^2)                     (magnitude of the vector)
143
Zn      = Zo+atan(Yo/Xo)                        (accumulated rotation angles or radians)
144
 
145
c, the cordic gain, is the product Pn of sqrt(1+2^(-2i)) and amounts to
146
approx. 1.64676 for n = 15.
147
 
148
In order to represent X, Y and Z as integers we introduce a scaling factor Q
149
which is chosen as follows:
150
1.      We normalize Xo and Yo (starting values) to be less than or equal to 1*Q and
151
        set Zo = 0 i.e. Xomax = 1*Q, Yomax = 1*Q, Zo = 0.
152
2.      With Xo = 1*Q and Yo = 1*Q, Xn will be Xnmax = Q*c*sqrt(2) = 2.329*Q
153
3.      In order to boost accuracy we only cover the rotation angles between 0 and PI/2
154
        i.e. X and Z are always > 0 and therefore can be unsigned.
155
        (We do the quadrant correction afterwards based on the initial signs of x and y)
156
4.      If X is an unsigned int, Xnmax = 65536, and Q = 65536/2.329 = 28140.
157
        i.e.
158
        Xnmax = 65536                                   --> unsigned int
159
        Ynmax = +/- 28140                               --> signed int
160
        Znmax = PI/2 * 28140 = 44202    --> unsigned int
161
        The systematic error is 90/44202 = 0.002036 degrees or 0.0000355 rad.
162
 
163
Below is atan2 and atan in C: */
164
 
165
#define getAtanVal(x)                   (uint16_t)pgm_read_word(&atantab[x])
166
 
167
const uint16_t atantab[T] PROGMEM = {22101,13047,6894,3499,1756,879,440,220,110,55,27,14,7,3,2,1};
168
 
169
int16_t my_atan2(int32_t y, int32_t x)
170
{       unsigned char i;
171
        uint32_t xQ;
172
        int32_t yQ;
173
        uint32_t angle = 0;
174
        uint32_t tmp;
175
        double x1, y1;
176
 
177
        x1 = abs(x);
178
        y1 = abs(y);
179
 
180
        if (y1 == 0) {
181
                if (x < 0)
182
                        return (180);
183
                else
184
                        return 0;
185
        }
186
 
187
        if (x1 < y1) {
188
                x1 /= y1;
189
                y1 = 1;
190
        }
191
        else {
192
                y1 /= x1;
193
                x1 = 1;
194
        }
195
 
196
        xQ = SCALED(x1);
197
        yQ = SCALED(y1);
198
 
199
        for (i = 0; i < T-1; i++) {
200
                tmp = xQ >> i;
201
                if (yQ < 0) {
202
                        xQ -= yQ >> i;
203
                        yQ += tmp;
204
                        angle -= getAtanVal(i);
205
                }
206
                else {
207
                        xQ += yQ >> i;
208
                        yQ -= tmp;
209
                        angle += getAtanVal(i);
210
                }
211
        }
212
 
213
        angle = RAD_TO_DEG * angle/Q;
214
        if (x <= 0)
215
                angle = 180 - angle;
216
        if (y <= 0)
217
                return(-angle);
218
        return(angle);
219
}
220