162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2011 Broadcom Corporation 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 1162306a36Sopenharmony_ci * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1362306a36Sopenharmony_ci * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1462306a36Sopenharmony_ci * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/cordic.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const s32 arctan_table[] = { 2062306a36Sopenharmony_ci 2949120, 2162306a36Sopenharmony_ci 1740967, 2262306a36Sopenharmony_ci 919879, 2362306a36Sopenharmony_ci 466945, 2462306a36Sopenharmony_ci 234379, 2562306a36Sopenharmony_ci 117304, 2662306a36Sopenharmony_ci 58666, 2762306a36Sopenharmony_ci 29335, 2862306a36Sopenharmony_ci 14668, 2962306a36Sopenharmony_ci 7334, 3062306a36Sopenharmony_ci 3667, 3162306a36Sopenharmony_ci 1833, 3262306a36Sopenharmony_ci 917, 3362306a36Sopenharmony_ci 458, 3462306a36Sopenharmony_ci 229, 3562306a36Sopenharmony_ci 115, 3662306a36Sopenharmony_ci 57, 3762306a36Sopenharmony_ci 29 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* 4162306a36Sopenharmony_ci * cordic_calc_iq() - calculates the i/q coordinate for given angle 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * theta: angle in degrees for which i/q coordinate is to be calculated 4462306a36Sopenharmony_ci * coord: function output parameter holding the i/q coordinate 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_cistruct cordic_iq cordic_calc_iq(s32 theta) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct cordic_iq coord; 4962306a36Sopenharmony_ci s32 angle, valtmp; 5062306a36Sopenharmony_ci unsigned iter; 5162306a36Sopenharmony_ci int signx = 1; 5262306a36Sopenharmony_ci int signtheta; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci coord.i = CORDIC_ANGLE_GEN; 5562306a36Sopenharmony_ci coord.q = 0; 5662306a36Sopenharmony_ci angle = 0; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci theta = CORDIC_FIXED(theta); 5962306a36Sopenharmony_ci signtheta = (theta < 0) ? -1 : 1; 6062306a36Sopenharmony_ci theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) - 6162306a36Sopenharmony_ci CORDIC_FIXED(180) * signtheta; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (CORDIC_FLOAT(theta) > 90) { 6462306a36Sopenharmony_ci theta -= CORDIC_FIXED(180); 6562306a36Sopenharmony_ci signx = -1; 6662306a36Sopenharmony_ci } else if (CORDIC_FLOAT(theta) < -90) { 6762306a36Sopenharmony_ci theta += CORDIC_FIXED(180); 6862306a36Sopenharmony_ci signx = -1; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci for (iter = 0; iter < CORDIC_NUM_ITER; iter++) { 7262306a36Sopenharmony_ci if (theta > angle) { 7362306a36Sopenharmony_ci valtmp = coord.i - (coord.q >> iter); 7462306a36Sopenharmony_ci coord.q += (coord.i >> iter); 7562306a36Sopenharmony_ci angle += arctan_table[iter]; 7662306a36Sopenharmony_ci } else { 7762306a36Sopenharmony_ci valtmp = coord.i + (coord.q >> iter); 7862306a36Sopenharmony_ci coord.q -= (coord.i >> iter); 7962306a36Sopenharmony_ci angle -= arctan_table[iter]; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci coord.i = valtmp; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci coord.i *= signx; 8562306a36Sopenharmony_ci coord.q *= signx; 8662306a36Sopenharmony_ci return coord; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ciEXPORT_SYMBOL(cordic_calc_iq); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciMODULE_DESCRIPTION("CORDIC algorithm"); 9162306a36Sopenharmony_ciMODULE_AUTHOR("Broadcom Corporation"); 9262306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 93