12c64e9cbSAndy Shevchenko /*
22c64e9cbSAndy Shevchenko * Copyright (c) 2011 Broadcom Corporation
32c64e9cbSAndy Shevchenko *
42c64e9cbSAndy Shevchenko * Permission to use, copy, modify, and/or distribute this software for any
52c64e9cbSAndy Shevchenko * purpose with or without fee is hereby granted, provided that the above
62c64e9cbSAndy Shevchenko * copyright notice and this permission notice appear in all copies.
72c64e9cbSAndy Shevchenko *
82c64e9cbSAndy Shevchenko * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
92c64e9cbSAndy Shevchenko * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
102c64e9cbSAndy Shevchenko * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
112c64e9cbSAndy Shevchenko * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
122c64e9cbSAndy Shevchenko * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
132c64e9cbSAndy Shevchenko * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
142c64e9cbSAndy Shevchenko * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
152c64e9cbSAndy Shevchenko */
162c64e9cbSAndy Shevchenko #include <linux/module.h>
172c64e9cbSAndy Shevchenko #include <linux/cordic.h>
182c64e9cbSAndy Shevchenko
192c64e9cbSAndy Shevchenko static const s32 arctan_table[] = {
202c64e9cbSAndy Shevchenko 2949120,
212c64e9cbSAndy Shevchenko 1740967,
222c64e9cbSAndy Shevchenko 919879,
232c64e9cbSAndy Shevchenko 466945,
242c64e9cbSAndy Shevchenko 234379,
252c64e9cbSAndy Shevchenko 117304,
262c64e9cbSAndy Shevchenko 58666,
272c64e9cbSAndy Shevchenko 29335,
282c64e9cbSAndy Shevchenko 14668,
292c64e9cbSAndy Shevchenko 7334,
302c64e9cbSAndy Shevchenko 3667,
312c64e9cbSAndy Shevchenko 1833,
322c64e9cbSAndy Shevchenko 917,
332c64e9cbSAndy Shevchenko 458,
342c64e9cbSAndy Shevchenko 229,
352c64e9cbSAndy Shevchenko 115,
362c64e9cbSAndy Shevchenko 57,
372c64e9cbSAndy Shevchenko 29
382c64e9cbSAndy Shevchenko };
392c64e9cbSAndy Shevchenko
402c64e9cbSAndy Shevchenko /*
412c64e9cbSAndy Shevchenko * cordic_calc_iq() - calculates the i/q coordinate for given angle
422c64e9cbSAndy Shevchenko *
432c64e9cbSAndy Shevchenko * theta: angle in degrees for which i/q coordinate is to be calculated
442c64e9cbSAndy Shevchenko * coord: function output parameter holding the i/q coordinate
452c64e9cbSAndy Shevchenko */
cordic_calc_iq(s32 theta)462c64e9cbSAndy Shevchenko struct cordic_iq cordic_calc_iq(s32 theta)
472c64e9cbSAndy Shevchenko {
482c64e9cbSAndy Shevchenko struct cordic_iq coord;
492c64e9cbSAndy Shevchenko s32 angle, valtmp;
502c64e9cbSAndy Shevchenko unsigned iter;
512c64e9cbSAndy Shevchenko int signx = 1;
522c64e9cbSAndy Shevchenko int signtheta;
532c64e9cbSAndy Shevchenko
542c64e9cbSAndy Shevchenko coord.i = CORDIC_ANGLE_GEN;
552c64e9cbSAndy Shevchenko coord.q = 0;
562c64e9cbSAndy Shevchenko angle = 0;
572c64e9cbSAndy Shevchenko
582c64e9cbSAndy Shevchenko theta = CORDIC_FIXED(theta);
592c64e9cbSAndy Shevchenko signtheta = (theta < 0) ? -1 : 1;
602c64e9cbSAndy Shevchenko theta = ((theta + CORDIC_FIXED(180) * signtheta) % CORDIC_FIXED(360)) -
612c64e9cbSAndy Shevchenko CORDIC_FIXED(180) * signtheta;
622c64e9cbSAndy Shevchenko
632c64e9cbSAndy Shevchenko if (CORDIC_FLOAT(theta) > 90) {
642c64e9cbSAndy Shevchenko theta -= CORDIC_FIXED(180);
652c64e9cbSAndy Shevchenko signx = -1;
662c64e9cbSAndy Shevchenko } else if (CORDIC_FLOAT(theta) < -90) {
672c64e9cbSAndy Shevchenko theta += CORDIC_FIXED(180);
682c64e9cbSAndy Shevchenko signx = -1;
692c64e9cbSAndy Shevchenko }
702c64e9cbSAndy Shevchenko
712c64e9cbSAndy Shevchenko for (iter = 0; iter < CORDIC_NUM_ITER; iter++) {
722c64e9cbSAndy Shevchenko if (theta > angle) {
732c64e9cbSAndy Shevchenko valtmp = coord.i - (coord.q >> iter);
742c64e9cbSAndy Shevchenko coord.q += (coord.i >> iter);
752c64e9cbSAndy Shevchenko angle += arctan_table[iter];
762c64e9cbSAndy Shevchenko } else {
772c64e9cbSAndy Shevchenko valtmp = coord.i + (coord.q >> iter);
782c64e9cbSAndy Shevchenko coord.q -= (coord.i >> iter);
792c64e9cbSAndy Shevchenko angle -= arctan_table[iter];
802c64e9cbSAndy Shevchenko }
812c64e9cbSAndy Shevchenko coord.i = valtmp;
822c64e9cbSAndy Shevchenko }
832c64e9cbSAndy Shevchenko
842c64e9cbSAndy Shevchenko coord.i *= signx;
852c64e9cbSAndy Shevchenko coord.q *= signx;
862c64e9cbSAndy Shevchenko return coord;
872c64e9cbSAndy Shevchenko }
882c64e9cbSAndy Shevchenko EXPORT_SYMBOL(cordic_calc_iq);
892c64e9cbSAndy Shevchenko
902c64e9cbSAndy Shevchenko MODULE_DESCRIPTION("CORDIC algorithm");
912c64e9cbSAndy Shevchenko MODULE_AUTHOR("Broadcom Corporation");
922c64e9cbSAndy Shevchenko MODULE_LICENSE("Dual BSD/GPL");
93