xref: /openbmc/linux/lib/math/cordic.c (revision 2c64e9cb)
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