Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (c) 2011 Broadcom Corporation
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0011  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
0013  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0014  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 #include <linux/module.h>
0017 #include <linux/cordic.h>
0018 
0019 #define CORDIC_ANGLE_GEN    39797
0020 #define CORDIC_PRECISION_SHIFT  16
0021 #define CORDIC_NUM_ITER     (CORDIC_PRECISION_SHIFT + 2)
0022 
0023 #define FIXED(X)    ((s32)((X) << CORDIC_PRECISION_SHIFT))
0024 #define FLOAT(X)    (((X) >= 0) \
0025         ? ((((X) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1) \
0026         : -((((-(X)) >> (CORDIC_PRECISION_SHIFT - 1)) + 1) >> 1))
0027 
0028 static const s32 arctan_table[] = {
0029     2949120,
0030     1740967,
0031     919879,
0032     466945,
0033     234379,
0034     117304,
0035     58666,
0036     29335,
0037     14668,
0038     7334,
0039     3667,
0040     1833,
0041     917,
0042     458,
0043     229,
0044     115,
0045     57,
0046     29
0047 };
0048 
0049 /*
0050  * cordic_calc_iq() - calculates the i/q coordinate for given angle
0051  *
0052  * theta: angle in degrees for which i/q coordinate is to be calculated
0053  * coord: function output parameter holding the i/q coordinate
0054  */
0055 struct cordic_iq cordic_calc_iq(s32 theta)
0056 {
0057     struct cordic_iq coord;
0058     s32 angle, valtmp;
0059     unsigned iter;
0060     int signx = 1;
0061     int signtheta;
0062 
0063     coord.i = CORDIC_ANGLE_GEN;
0064     coord.q = 0;
0065     angle = 0;
0066 
0067     theta = FIXED(theta);
0068     signtheta = (theta < 0) ? -1 : 1;
0069     theta = ((theta + FIXED(180) * signtheta) % FIXED(360)) -
0070         FIXED(180) * signtheta;
0071 
0072     if (FLOAT(theta) > 90) {
0073         theta -= FIXED(180);
0074         signx = -1;
0075     } else if (FLOAT(theta) < -90) {
0076         theta += FIXED(180);
0077         signx = -1;
0078     }
0079 
0080     for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
0081         if (theta > angle) {
0082             valtmp = coord.i - (coord.q >> iter);
0083             coord.q += (coord.i >> iter);
0084             angle += arctan_table[iter];
0085         } else {
0086             valtmp = coord.i + (coord.q >> iter);
0087             coord.q -= (coord.i >> iter);
0088             angle -= arctan_table[iter];
0089         }
0090         coord.i = valtmp;
0091     }
0092 
0093     coord.i *= signx;
0094     coord.q *= signx;
0095     return coord;
0096 }
0097 EXPORT_SYMBOL(cordic_calc_iq);
0098 
0099 MODULE_DESCRIPTION("CORDIC algorithm");
0100 MODULE_AUTHOR("Broadcom Corporation");
0101 MODULE_LICENSE("Dual BSD/GPL");