Skip to content

Commit 10f8113

Browse files
Arend van Spriellinvjw
authored andcommitted
lib: cordic: add library module providing cordic angle calculation
The brcm80211 driver in the staging tree has a cordic function to determine cosine and sine for a given angle. Feedback received from John Linville suggested that these kind of functions should be made available to others as a library function in the kernel tree. The b43 driver also has a cordic angle calculation implemented. Cc: [email protected] Cc: [email protected] Cc: "John W. Linville" <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Dan Carpenter <[email protected]> Cc: Randy Dunlap <[email protected]> Cc: Larry Finger <[email protected]> Reviewed-by: Roland Vossen <[email protected]> Reviewed-by: Henry Ptasinski <[email protected]> Reviewed-by: Franky (Zhenhui) Lin <[email protected]> Signed-off-by: Arend van Spriel <[email protected]> Signed-off-by: John W. Linville <[email protected]>
1 parent 7150962 commit 10f8113

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

include/linux/cordic.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
#ifndef __CORDIC_H_
17+
#define __CORDIC_H_
18+
19+
#include <linux/types.h>
20+
21+
/**
22+
* struct cordic_iq - i/q coordinate.
23+
*
24+
* @i: real part of coordinate (in phase).
25+
* @q: imaginary part of coordinate (quadrature).
26+
*/
27+
struct cordic_iq {
28+
s32 i;
29+
s32 q;
30+
};
31+
32+
/**
33+
* cordic_calc_iq() - calculates the i/q coordinate for given angle.
34+
*
35+
* @theta: angle in degrees for which i/q coordinate is to be calculated.
36+
* @coord: function output parameter holding the i/q coordinate.
37+
*
38+
* The function calculates the i/q coordinate for a given angle using
39+
* cordic algorithm. The coordinate consists of a real (i) and an
40+
* imaginary (q) part. The real part is essentially the cosine of the
41+
* angle and the imaginary part is the sine of the angle. The returned
42+
* values are scaled by 2^16 for precision. The range for theta is
43+
* for -180 degrees to +180 degrees. Passed values outside this range are
44+
* converted before doing the actual calculation.
45+
*/
46+
struct cordic_iq cordic_calc_iq(s32 theta);
47+
48+
#endif /* __CORDIC_H_ */

lib/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,11 @@ config AVERAGE
279279

280280
If unsure, say N.
281281

282+
config CORDIC
283+
tristate "Cordic function"
284+
help
285+
The option provides arithmetic function using cordic algorithm
286+
so its calculations are in fixed point. Modules can select this
287+
when they require this function. Module will be called cordic.
288+
282289
endmenu

lib/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ obj-$(CONFIG_AVERAGE) += average.o
117117

118118
obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
119119

120+
obj-$(CONFIG_CORDIC) += cordic.o
121+
120122
hostprogs-y := gen_crc32table
121123
clean-files := crc32table.h
122124

lib/cordic.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
#define CORDIC_ANGLE_GEN 39797
20+
#define CORDIC_PRECISION_SHIFT 16
21+
#define CORDIC_NUM_ITER (CORDIC_PRECISION_SHIFT + 2)
22+
23+
#define FIXED(X) ((s32)((X) << CORDIC_PRECISION_SHIFT))
24+
#define FLOAT(X) (((X) >= 0) \
25+
? ((((X) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1) \
26+
: -((((-(X)) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1))
27+
28+
static const s32 arctan_table[] = {
29+
2949120,
30+
1740967,
31+
919879,
32+
466945,
33+
234379,
34+
117304,
35+
58666,
36+
29335,
37+
14668,
38+
7334,
39+
3667,
40+
1833,
41+
917,
42+
458,
43+
229,
44+
115,
45+
57,
46+
29
47+
};
48+
49+
/*
50+
* cordic_calc_iq() - calculates the i/q coordinate for given angle
51+
*
52+
* theta: angle in degrees for which i/q coordinate is to be calculated
53+
* coord: function output parameter holding the i/q coordinate
54+
*/
55+
struct cordic_iq cordic_calc_iq(s32 theta)
56+
{
57+
struct cordic_iq coord;
58+
s32 angle, valtmp;
59+
unsigned iter;
60+
int signx = 1;
61+
int signtheta;
62+
63+
coord.i = CORDIC_ANGLE_GEN;
64+
coord.q = 0;
65+
angle = 0;
66+
67+
theta = FIXED(theta);
68+
signtheta = (theta < 0) ? -1 : 1;
69+
theta = ((theta + FIXED(180) * signtheta) % FIXED(360)) -
70+
FIXED(180) * signtheta;
71+
72+
if (FLOAT(theta) > 90) {
73+
theta -= FIXED(180);
74+
signx = -1;
75+
} else if (FLOAT(theta) < -90) {
76+
theta += FIXED(180);
77+
signx = -1;
78+
}
79+
80+
for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
81+
if (theta > angle) {
82+
valtmp = coord.i - (coord.q >> iter);
83+
coord.q += (coord.i >> iter);
84+
angle += arctan_table[iter];
85+
} else {
86+
valtmp = coord.i + (coord.q >> iter);
87+
coord.q -= (coord.i >> iter);
88+
angle -= arctan_table[iter];
89+
}
90+
coord.i = valtmp;
91+
}
92+
93+
coord.i *= signx;
94+
coord.q *= signx;
95+
return coord;
96+
}
97+
EXPORT_SYMBOL(cordic_calc_iq);
98+
99+
MODULE_DESCRIPTION("Cordic functions");
100+
MODULE_AUTHOR("Broadcom Corporation");
101+
MODULE_LICENSE("Dual BSD/GPL");

0 commit comments

Comments
 (0)