Rev 2147 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2147 | Rev 2212 | ||
---|---|---|---|
1 | /****************************************************************/ |
1 | /****************************************************************/ |
2 | /* */ |
2 | /* */ |
3 | /* NG-Video 5,8GHz */ |
3 | /* NG-Video 5,8GHz */ |
4 | /* */ |
4 | /* */ |
5 | /* Copyright (C) 2011 - gebad */ |
5 | /* Copyright (C) 2011 - gebad */ |
6 | /* */ |
6 | /* */ |
7 | /* This code is distributed under the GNU Public License */ |
7 | /* This code is distributed under the GNU Public License */ |
8 | /* which can be found at http://www.gnu.org/licenses/gpl.txt */ |
8 | /* which can be found at http://www.gnu.org/licenses/gpl.txt */ |
9 | /* */ |
9 | /* */ |
10 | /****************************************************************/ |
10 | /****************************************************************/ |
11 | 11 | ||
12 | //############################################################################ |
12 | //############################################################################ |
13 | //# HISTORY mymath.c |
13 | //# HISTORY mymath.c |
14 | //# |
14 | //# |
15 | //# 24.04.2013 OG |
15 | //# 24.04.2013 OG |
16 | //# - chg: 'uint16_t atantab[T] PROGMEM' nach 'const uint16_t atantab[T] PROGMEM' |
16 | //# - chg: 'uint16_t atantab[T] PROGMEM' nach 'const uint16_t atantab[T] PROGMEM' |
17 | //# wegen Compile-Error in AtmelStudio 6 |
17 | //# wegen Compile-Error in AtmelStudio 6 |
18 | //############################################################################ |
18 | //############################################################################ |
19 | 19 | ||
20 | 20 | ||
21 | #include <stdio.h> |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
22 | #include <stdlib.h> |
23 | #include <math.h> |
23 | #include <math.h> |
24 | #include <avr/pgmspace.h> |
24 | #include <avr/pgmspace.h> |
25 | 25 | ||
26 | #include "mymath.h" |
26 | #include "mymath.h" |
27 | 27 | ||
28 | // http://www.mikrocontroller.net/articles/AVR_Arithmetik#avr-gcc_Implementierung_.2832_Bit.29 |
28 | // http://www.mikrocontroller.net/articles/AVR_Arithmetik#avr-gcc_Implementierung_.2832_Bit.29 |
29 | unsigned int sqrt32(uint32_t q) |
29 | unsigned int sqrt32(uint32_t q) |
30 | { uint16_t r, mask; |
30 | { uint16_t r, mask; |
31 | uint16_t i = 8*sizeof (r) -1; |
31 | uint16_t i = 8*sizeof (r) -1; |
32 | 32 | ||
33 | r = mask = 1 << i; |
33 | r = mask = 1 << i; |
34 | for (; i > 0; i--) { |
34 | for (; i > 0; i--) { |
35 | mask >>= 1; |
35 | mask >>= 1; |
36 | 36 | ||
37 | if (q < (uint32_t) r*r) |
37 | if (q < (uint32_t) r*r) |
38 | r -= mask; |
38 | r -= mask; |
39 | else |
39 | else |
40 | r += mask; |
40 | r += mask; |
41 | } |
41 | } |
42 | 42 | ||
43 | if (q < (uint32_t) r*r) |
43 | if (q < (uint32_t) r*r) |
44 | r -= 1; |
44 | r -= 1; |
45 | 45 | ||
46 | return r; |
46 | return r; |
47 | } |
47 | } |
48 | 48 | ||
49 | // aus Orginal MK source code |
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. |
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, \ |
51 | const int16_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, \ |
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, \ |
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, \ |
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, \ |
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, \ |
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, \ |
57 | 7834, 7875, 7913, 7949, 7982, 8013, 8041, 8068, 8091, 8112, 8131, 8147, \ |
58 | 8161, 8172, 8181, 8187, 8191, 8192}; |
58 | 8161, 8172, 8181, 8187, 8191, 8192}; |
59 | - | ||
- | 59 | ||
60 | //double c_cos_8192(int16_t angle) |
60 | |
61 | int16_t c_cos_8192(int16_t angle) |
61 | int16_t c_cos_8192(int16_t angle) |
- | 62 | { |
|
- | 63 | return (c_sin_8192(90 - angle)); |
|
- | 64 | } |
|
- | 65 | ||
- | 66 | ||
- | 67 | ||
- | 68 | int16_t c_sin_8192(int16_t angle) |
|
62 | { |
69 | { |
63 | int8_t m,n; |
70 | int8_t m, n; |
64 | int16_t sinus; |
- | |
65 | 71 | int16_t sinus; |
|
66 | angle = 90 - angle; |
72 | |
67 | // avoid negative angles |
73 | // avoid negative angles |
68 | if (angle < 0) |
74 | if (angle < 0) |
69 | { |
75 | { |
70 | m = -1; |
76 | m = -1; |
71 | angle = -angle; |
77 | angle = -angle; |
72 | } |
78 | } |
73 | else m = +1; |
79 | else m = +1; |
74 | 80 | ||
75 | // fold angle to interval 0 to 359 |
81 | // fold angle to interval 0 to 359 |
76 | angle %= 360; |
82 | angle %= 360; |
77 | 83 | ||
78 | // check quadrant |
84 | // check quadrant |
79 | if (angle <= 90) n = 1; // first quadrant |
85 | if (angle <= 90) n = 1; // first quadrant |
80 | else if ((angle > 90) && (angle <= 180)) {angle = 180 - angle; n = 1;} // second quadrant |
86 | 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 |
87 | else if ((angle > 180) && (angle <= 270)) {angle = angle - 180; n = -1;} // third quadrant |
82 | else {angle = 360 - angle; n = -1;} //fourth quadrant |
88 | else {angle = 360 - angle; n = -1;} //fourth quadrant |
83 | // get lookup value |
89 | // get lookup value |
84 | sinus = sinlookup[angle]; |
90 | sinus = sinlookup[angle]; |
85 | // calculate sinus value |
91 | // calculate sinus value |
86 | return (sinus * m * n); |
92 | return (sinus * m * n); |
87 | } |
93 | } |
88 | 94 | ||
89 | // ---------------------------------------------------------------------------------------------- |
95 | // ---------------------------------------------------------------------------------------------- |
90 | 96 | ||
91 | 97 | ||
92 | const int16_t arccos64[65] = {90,89,88,87,86, 85, 84, 83, 83, 82, 81, 80, 79, 78, 77, 76, |
98 | 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, |
99 | 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, |
100 | 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, |
101 | 44, 43, 41, 40, 39, 37, 36, 34, 32, 31, 29, 27, 25, 23, 20, |
96 | 18, 14, 10, 0}; |
102 | 18, 14, 10, 0}; |
97 | 103 | ||
98 | 104 | ||
99 | 105 | ||
100 | int16_t c_arccos2(int32_t a, int32_t b) |
106 | int16_t c_arccos2(int32_t a, int32_t b) |
101 | { |
107 | { |
102 | if(a>b) return(0); |
108 | if(a>b) return(0); |
103 | return(arccos64[64 * a / b]); |
109 | return(arccos64[64 * a / b]); |
104 | } |
110 | } |
105 | 111 | ||
106 | 112 | ||
107 | /* ---------------------------------------------------------------------------------------------- |
113 | /* ---------------------------------------------------------------------------------------------- |
108 | 114 | ||
109 | atan2.S |
115 | atan2.S |
110 | 116 | ||
111 | Author: Reiner Patommel |
117 | Author: Reiner Patommel |
112 | |
118 | |
113 | atan2.S uses CORDIC, an algorithm which was developed in 1956 by Jack Volder. |
119 | 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 |
120 | CORDIC can be used to calculate trigonometric, hyperbolic and linear |
115 | functions and is until today implemented in most pocket calculators. |
121 | functions and is until today implemented in most pocket calculators. |
116 | The algorithm makes only use of simple integer arithmetic. |
122 | The algorithm makes only use of simple integer arithmetic. |
117 | 123 | ||
118 | The CORDIC equations in vectoring mode for trigonometric functions are: |
124 | The CORDIC equations in vectoring mode for trigonometric functions are: |
119 | Xi+1 = Xi - Si * (Yi * 1 / 2^i) |
125 | Xi+1 = Xi - Si * (Yi * 1 / 2^i) |
120 | Yi+1 = Yi + Si * (Xi * 1 / 2^i) |
126 | Yi+1 = Yi + Si * (Xi * 1 / 2^i) |
121 | Zi+1 = Zi - Si * atan(1 / 2^i) |
127 | Zi+1 = Zi - Si * atan(1 / 2^i) |
122 | where Si = +1 if Yi < 0 else Si = -1 |
128 | where Si = +1 if Yi < 0 else Si = -1 |
123 | The rotation angles are limited to -PI/2 and PI/2 i.e. |
129 | The rotation angles are limited to -PI/2 and PI/2 i.e. |
124 | -90 degrees ... +90 degrees |
130 | -90 degrees ... +90 degrees |
125 | 131 | ||
126 | For the calculation of atan2(x,y) we need a small pre-calculated table of |
132 | 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). |
133 | 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 |
134 | 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 |
135 | 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 |
136 | 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 |
137 | 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). |
138 | step is 45 degrees, the last step is 0.002036 degrees for n = 15). |
133 | 139 | ||
134 | After n rotations the variables will have the following values: |
140 | After n rotations the variables will have the following values: |
135 | Yn = ideally 0 |
141 | Yn = ideally 0 |
136 | Xn = c*sqrt(Xo^2+Yo^2) (magnitude of the vector) |
142 | Xn = c*sqrt(Xo^2+Yo^2) (magnitude of the vector) |
137 | Zn = Zo+atan(Yo/Xo) (accumulated rotation angles or radians) |
143 | Zn = Zo+atan(Yo/Xo) (accumulated rotation angles or radians) |
138 | 144 | ||
139 | c, the cordic gain, is the product Pn of sqrt(1+2^(-2i)) and amounts to |
145 | c, the cordic gain, is the product Pn of sqrt(1+2^(-2i)) and amounts to |
140 | approx. 1.64676 for n = 15. |
146 | approx. 1.64676 for n = 15. |
141 | 147 | ||
142 | In order to represent X, Y and Z as integers we introduce a scaling factor Q |
148 | In order to represent X, Y and Z as integers we introduce a scaling factor Q |
143 | which is chosen as follows: |
149 | which is chosen as follows: |
144 | 1. We normalize Xo and Yo (starting values) to be less than or equal to 1*Q and |
150 | 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. |
151 | 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 |
152 | 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 |
153 | 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. |
154 | 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) |
155 | (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. |
156 | 4. If X is an unsigned int, Xnmax = 65536, and Q = 65536/2.329 = 28140. |
151 | i.e. |
157 | i.e. |
152 | Xnmax = 65536 --> unsigned int |
158 | Xnmax = 65536 --> unsigned int |
153 | Ynmax = +/- 28140 --> signed int |
159 | Ynmax = +/- 28140 --> signed int |
154 | Znmax = PI/2 * 28140 = 44202 --> unsigned int |
160 | Znmax = PI/2 * 28140 = 44202 --> unsigned int |
155 | The systematic error is 90/44202 = 0.002036 degrees or 0.0000355 rad. |
161 | The systematic error is 90/44202 = 0.002036 degrees or 0.0000355 rad. |
156 | |
162 | |
157 | Below is atan2 and atan in C: */ |
163 | Below is atan2 and atan in C: */ |
158 | 164 | ||
159 | #define getAtanVal(x) (uint16_t)pgm_read_word(&atantab[x]) |
165 | #define getAtanVal(x) (uint16_t)pgm_read_word(&atantab[x]) |
160 | 166 | ||
161 | const uint16_t atantab[T] PROGMEM = {22101,13047,6894,3499,1756,879,440,220,110,55,27,14,7,3,2,1}; |
167 | const uint16_t atantab[T] PROGMEM = {22101,13047,6894,3499,1756,879,440,220,110,55,27,14,7,3,2,1}; |
162 | 168 | ||
163 | int16_t my_atan2(int32_t y, int32_t x) |
169 | int16_t my_atan2(int32_t y, int32_t x) |
164 | { unsigned char i; |
170 | { unsigned char i; |
165 | uint32_t xQ; |
171 | uint32_t xQ; |
166 | int32_t yQ; |
172 | int32_t yQ; |
167 | uint32_t angle = 0; |
173 | uint32_t angle = 0; |
168 | uint32_t tmp; |
174 | uint32_t tmp; |
169 | double x1, y1; |
175 | double x1, y1; |
170 | 176 | ||
171 | x1 = abs(x); |
177 | x1 = abs(x); |
172 | y1 = abs(y); |
178 | y1 = abs(y); |
173 | 179 | ||
174 | if (y1 == 0) { |
180 | if (y1 == 0) { |
175 | if (x < 0) |
181 | if (x < 0) |
176 | return (180); |
182 | return (180); |
177 | else |
183 | else |
178 | return 0; |
184 | return 0; |
179 | } |
185 | } |
180 | 186 | ||
181 | if (x1 < y1) { |
187 | if (x1 < y1) { |
182 | x1 /= y1; |
188 | x1 /= y1; |
183 | y1 = 1; |
189 | y1 = 1; |
184 | } |
190 | } |
185 | else { |
191 | else { |
186 | y1 /= x1; |
192 | y1 /= x1; |
187 | x1 = 1; |
193 | x1 = 1; |
188 | } |
194 | } |
189 | 195 | ||
190 | xQ = SCALED(x1); |
196 | xQ = SCALED(x1); |
191 | yQ = SCALED(y1); |
197 | yQ = SCALED(y1); |
192 | 198 | ||
193 | for (i = 0; i < T-1; i++) { |
199 | for (i = 0; i < T-1; i++) { |
194 | tmp = xQ >> i; |
200 | tmp = xQ >> i; |
195 | if (yQ < 0) { |
201 | if (yQ < 0) { |
196 | xQ -= yQ >> i; |
202 | xQ -= yQ >> i; |
197 | yQ += tmp; |
203 | yQ += tmp; |
198 | angle -= getAtanVal(i); |
204 | angle -= getAtanVal(i); |
199 | } |
205 | } |
200 | else { |
206 | else { |
201 | xQ += yQ >> i; |
207 | xQ += yQ >> i; |
202 | yQ -= tmp; |
208 | yQ -= tmp; |
203 | angle += getAtanVal(i); |
209 | angle += getAtanVal(i); |
204 | } |
210 | } |
205 | } |
211 | } |
206 | 212 | ||
207 | angle = RAD_TO_DEG * angle/Q; |
213 | angle = RAD_TO_DEG * angle/Q; |
208 | if (x <= 0) |
214 | if (x <= 0) |
209 | angle = 180 - angle; |
215 | angle = 180 - angle; |
210 | if (y <= 0) |
216 | if (y <= 0) |
211 | return(-angle); |
217 | return(-angle); |
212 | return(angle); |
218 | return(angle); |
213 | } |
219 | } |
214 | 220 | ||
215 | 221 |