Back to home page

OSCL-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 static const s32 arctan_table[] = {
0020     2949120,
0021     1740967,
0022     919879,
0023     466945,
0024     234379,
0025     117304,
0026     58666,
0027     29335,
0028     14668,
0029     7334,
0030     3667,
0031     1833,
0032     917,
0033     458,
0034     229,
0035     115,
0036     57,
0037     29
0038 };
0039 
0040 /*
0041  * cordic_calc_iq() - calculates the i/q coordinate for given angle
0042  *
0043  * theta: angle in degrees for which i/q coordinate is to be calculated
0044  * coord: function output parameter holding the i/q coordinate
0045  */
0046 struct cordic_iq cordic_calc_iq(s32 theta)
0047 {
0048     struct cordic_iq coord;
0049     s32 angle, valtmp;
0050     unsigned iter;
0051     int signx = 1;
0052     int signtheta;
0053 
0054     coord.i = CORDIC_ANGLE_GEN;
0055     coord.q = 0;
0056     angle = 0;
0057 
0058     theta = CORDIC_FIXED(theta);
0059     signtheta = (theta < 0) ? -1 : 1;
0060     theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) -
0061         CORDIC_FIXED(180) * signtheta;
0062 
0063     if (CORDIC_FLOAT(theta) > 90) {
0064         theta -= CORDIC_FIXED(180);
0065         signx = -1;
0066     } else if (CORDIC_FLOAT(theta) < -90) {
0067         theta += CORDIC_FIXED(180);
0068         signx = -1;
0069     }
0070 
0071     for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
0072         if (theta > angle) {
0073             valtmp = coord.i - (coord.q >> iter);
0074             coord.q += (coord.i >> iter);
0075             angle += arctan_table[iter];
0076         } else {
0077             valtmp = coord.i + (coord.q >> iter);
0078             coord.q -= (coord.i >> iter);
0079             angle -= arctan_table[iter];
0080         }
0081         coord.i = valtmp;
0082     }
0083 
0084     coord.i *= signx;
0085     coord.q *= signx;
0086     return coord;
0087 }
0088 EXPORT_SYMBOL(cordic_calc_iq);
0089 
0090 MODULE_DESCRIPTION("CORDIC algorithm");
0091 MODULE_AUTHOR("Broadcom Corporation");
0092 MODULE_LICENSE("Dual BSD/GPL");