1 | /* |
2 | * Copyright (c) 2011 Broadcom Corporation |
3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | #include <linux/module.h> |
17 | #include <linux/cordic.h> |
18 | |
19 | static const s32 arctan_table[] = { |
20 | 2949120, |
21 | 1740967, |
22 | 919879, |
23 | 466945, |
24 | 234379, |
25 | 117304, |
26 | 58666, |
27 | 29335, |
28 | 14668, |
29 | 7334, |
30 | 3667, |
31 | 1833, |
32 | 917, |
33 | 458, |
34 | 229, |
35 | 115, |
36 | 57, |
37 | 29 |
38 | }; |
39 | |
40 | /* |
41 | * cordic_calc_iq() - calculates the i/q coordinate for given angle |
42 | * |
43 | * theta: angle in degrees for which i/q coordinate is to be calculated |
44 | * coord: function output parameter holding the i/q coordinate |
45 | */ |
46 | struct cordic_iq cordic_calc_iq(s32 theta) |
47 | { |
48 | struct cordic_iq coord; |
49 | s32 angle, valtmp; |
50 | unsigned iter; |
51 | int signx = 1; |
52 | int signtheta; |
53 | |
54 | coord.i = CORDIC_ANGLE_GEN; |
55 | coord.q = 0; |
56 | angle = 0; |
57 | |
58 | theta = CORDIC_FIXED(theta); |
59 | signtheta = (theta < 0) ? -1 : 1; |
60 | theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) - |
61 | CORDIC_FIXED(180) * signtheta; |
62 | |
63 | if (CORDIC_FLOAT(theta) > 90) { |
64 | theta -= CORDIC_FIXED(180); |
65 | signx = -1; |
66 | } else if (CORDIC_FLOAT(theta) < -90) { |
67 | theta += CORDIC_FIXED(180); |
68 | signx = -1; |
69 | } |
70 | |
71 | for (iter = 0; iter < CORDIC_NUM_ITER; iter++) { |
72 | if (theta > angle) { |
73 | valtmp = coord.i - (coord.q >> iter); |
74 | coord.q += (coord.i >> iter); |
75 | angle += arctan_table[iter]; |
76 | } else { |
77 | valtmp = coord.i + (coord.q >> iter); |
78 | coord.q -= (coord.i >> iter); |
79 | angle -= arctan_table[iter]; |
80 | } |
81 | coord.i = valtmp; |
82 | } |
83 | |
84 | coord.i *= signx; |
85 | coord.q *= signx; |
86 | return coord; |
87 | } |
88 | EXPORT_SYMBOL(cordic_calc_iq); |
89 | |
90 | MODULE_DESCRIPTION("CORDIC algorithm" ); |
91 | MODULE_AUTHOR("Broadcom Corporation" ); |
92 | MODULE_LICENSE("Dual BSD/GPL" ); |
93 | |