1 |
2 |
kavi |
//
|
2 |
|
|
// Filename: cordic.c
|
3 |
|
|
// Purpose : N-address code (NAC) implementation for a fixed-point universal
|
4 |
|
|
// CORDIC. The arithmetic representation used is signed fixed-point
|
5 |
|
|
// (Q2.14S). The implementation has been generated by a modified
|
6 |
|
|
// version of the simple fixed-point CORDIC tools from:
|
7 |
|
|
// http://www.dcs.gla.ac.uk/~jhw/cordic/
|
8 |
|
|
// Author : Nikolaos Kavvadias (C) 2010
|
9 |
|
|
// Date : 31-Oct-2010
|
10 |
|
|
// Revision: 0.3.0 (31/10/10)
|
11 |
|
|
// Initial version.
|
12 |
|
|
// 0.3.1 (08/11/10)
|
13 |
|
|
// Description of the universal CORDIC algorithm is finalized.
|
14 |
|
|
//
|
15 |
|
|
#include <stdio.h>
|
16 |
|
|
#include <math.h>
|
17 |
|
|
|
18 |
|
|
#define ROTATION 0
|
19 |
|
|
#define VECTORING 1
|
20 |
|
|
#define CIRCULAR 0
|
21 |
|
|
#define LINEAR 1
|
22 |
|
|
#define HYPERBOLIC 2
|
23 |
|
|
|
24 |
|
|
typedef short int integer;
|
25 |
|
|
//typedef integer int;
|
26 |
|
|
|
27 |
|
|
//Cordic in 16 bit signed fixed point math
|
28 |
|
|
//Function is valid for arguments in range -pi/2 -- pi/2
|
29 |
|
|
//for values pi/2--pi: value = half_pi-(theta-half_pi) and similarly for values -pi---pi/2
|
30 |
|
|
//
|
31 |
|
|
// 1.0 = 16384
|
32 |
|
|
// 1/k = 0.6072529350088812561694
|
33 |
|
|
// pi = 3.1415926536897932384626
|
34 |
|
|
//Constants
|
35 |
|
|
#define MY_PI 3.1415926536897932384626
|
36 |
|
|
// Q2.14S
|
37 |
|
|
#define cordic_1K 9949
|
38 |
|
|
#define cordic_1Kp 19783
|
39 |
|
|
#define half_pi 25735
|
40 |
|
|
#define MUL 16384.000000
|
41 |
|
|
#define CORDIC_NTAB 14
|
42 |
|
|
integer cordic_tab[3*CORDIC_NTAB] = {
|
43 |
|
|
65535 /* NOT USED */, 8999, 4184, 2058, 1025, 512, 256, 128, 64, 32, 16, 8, 4, 2, /* HYPERBOLIC */
|
44 |
|
|
16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, /* LINEAR */
|
45 |
|
|
12867, 7596, 4013, 2037, 1022, 511, 255, 127, 63, 31, 15, 7, 3, 1 /* CIRCULAR */
|
46 |
|
|
};
|
47 |
|
|
// for convergence in hyperbolic mode, steps 4 and 13 must be repeated
|
48 |
|
|
integer cordic_hyp_steps[] = {
|
49 |
|
|
// 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
|
50 |
|
|
1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13
|
51 |
|
|
};
|
52 |
|
|
integer gdirection; // {0: ROTATION, 1: VECTORING}
|
53 |
|
|
integer gmode; // {0: CIRCULAR, 1: LINEAR, 2: HYPERBOLIC}
|
54 |
|
|
|
55 |
|
|
void cordicopt(integer direction, integer mode, integer xin, integer yin, integer zin, integer *xout, integer *yout, integer *zout)
|
56 |
|
|
{
|
57 |
|
|
integer k, kk, d, x1, x2, y1, y2, z1, z2;
|
58 |
|
|
integer x, y, z;
|
59 |
|
|
integer kstart, kfinal, xbyk, ybyk, tabval;
|
60 |
|
|
integer offset;
|
61 |
|
|
|
62 |
|
|
x = xin;
|
63 |
|
|
y = yin;
|
64 |
|
|
z = zin;
|
65 |
|
|
offset = ((mode == HYPERBOLIC) ? 0 : ((mode == LINEAR) ? 14 : 28));
|
66 |
|
|
kfinal = ((mode != HYPERBOLIC) ? CORDIC_NTAB : CORDIC_NTAB+1);
|
67 |
|
|
for (k = 0; k < kfinal; k++)
|
68 |
|
|
{
|
69 |
|
|
d = ((direction == ROTATION) ? ((z>=0) ? 0 : 1) : ((y<0) ? 0 : 1));
|
70 |
|
|
kk = ((mode != HYPERBOLIC) ? k : cordic_hyp_steps[k]);
|
71 |
|
|
xbyk = (x>>kk);
|
72 |
|
|
ybyk = ((mode == HYPERBOLIC) ? -(y>>kk) : ((mode == LINEAR) ? 0 : (y>>kk)));
|
73 |
|
|
tabval = cordic_tab[kk+offset];
|
74 |
|
|
x1 = x - ybyk;
|
75 |
|
|
x2 = x + ybyk;
|
76 |
|
|
y1 = y + xbyk;
|
77 |
|
|
y2 = y - xbyk;
|
78 |
|
|
z1 = z - tabval;
|
79 |
|
|
z2 = z + tabval;
|
80 |
|
|
x = ((d == 0) ? x1 : x2);
|
81 |
|
|
y = ((d == 0) ? y1 : y2);
|
82 |
|
|
z = ((d == 0) ? z1 : z2);
|
83 |
|
|
}
|
84 |
|
|
*xout = x;
|
85 |
|
|
*yout = y;
|
86 |
|
|
*zout = z;
|
87 |
|
|
}
|
88 |
|
|
|
89 |
|
|
int main(int argc, char **argv)
|
90 |
|
|
{
|
91 |
|
|
double p;
|
92 |
|
|
integer x1, y1, z1, x2, y2, z2, i, temp;
|
93 |
|
|
integer w1;
|
94 |
|
|
|
95 |
|
|
// ROTATION, SIN/COS
|
96 |
|
|
#ifndef DATAGEN
|
97 |
|
|
printf("SINE, COSINE\n");
|
98 |
|
|
#endif
|
99 |
|
|
gdirection = ROTATION; gmode = CIRCULAR;
|
100 |
|
|
x1 = cordic_1K; y1 = 0;
|
101 |
|
|
for (i = 0; i < 50; i++)
|
102 |
|
|
{
|
103 |
|
|
p = (i/50.0)*MY_PI/2;
|
104 |
|
|
z1 = (integer)(p * MUL);
|
105 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
106 |
|
|
#ifdef DATAGEN
|
107 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
108 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
109 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
110 |
|
|
#else
|
111 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
112 |
|
|
// results.
|
113 |
|
|
printf("%f : cos=%f (%f), sin=%f (%f)\n", p, x2/MUL, cos(p), y2/MUL, sin(p));
|
114 |
|
|
#endif
|
115 |
|
|
}
|
116 |
|
|
|
117 |
|
|
// VECTORING, ATAN
|
118 |
|
|
#ifndef DATAGEN
|
119 |
|
|
printf("\nARCTAN\n");
|
120 |
|
|
#endif
|
121 |
|
|
gdirection = VECTORING; gmode = CIRCULAR;
|
122 |
|
|
z1 = 0;
|
123 |
|
|
for (x1 = 0; x1 <= 7000; x1+=500)
|
124 |
|
|
{
|
125 |
|
|
for (y1 = 0; y1 <= 7000; y1+=500)
|
126 |
|
|
{
|
127 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
128 |
|
|
#ifdef DATAGEN
|
129 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
130 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
131 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
132 |
|
|
#else
|
133 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
134 |
|
|
// results.
|
135 |
|
|
printf("%d/%d: atan=%f (%f), y2 = %d\n", y1, x1, z2/MUL, atan((double)y1/x1), y2);
|
136 |
|
|
#endif
|
137 |
|
|
}
|
138 |
|
|
}
|
139 |
|
|
|
140 |
|
|
// HYPERBOLIC, VECTORING, SQUARE ROOT
|
141 |
|
|
#ifndef DATAGEN
|
142 |
|
|
printf("\nSQUARE ROOT\n");
|
143 |
|
|
#endif
|
144 |
|
|
gdirection = VECTORING; gmode = HYPERBOLIC;
|
145 |
|
|
z1 = 0;
|
146 |
|
|
for (w1 = 100; w1 <= 7000; w1+=100)
|
147 |
|
|
{
|
148 |
|
|
x1 = w1+(1<<12);
|
149 |
|
|
y1 = w1-(1<<12);
|
150 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
151 |
|
|
#ifdef DATAGEN
|
152 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
153 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
154 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
155 |
|
|
#else
|
156 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
157 |
|
|
// results.
|
158 |
|
|
printf("%d: sqrt=%f (%f)\n", w1, (cordic_1Kp/MUL)*x2/MUL, sqrt((double)w1/MUL));
|
159 |
|
|
#endif
|
160 |
|
|
}
|
161 |
|
|
|
162 |
|
|
// LINEAR, VECTORING, RECIPROCAL
|
163 |
|
|
#ifndef DATAGEN
|
164 |
|
|
printf("\nRECIPROCAL\n");
|
165 |
|
|
#endif
|
166 |
|
|
gdirection = VECTORING; gmode = LINEAR;
|
167 |
|
|
z1 = 0;
|
168 |
|
|
y1 = (1<<14);
|
169 |
|
|
for (x1 = 32000; x1 > 8000; x1-=250)
|
170 |
|
|
{
|
171 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
172 |
|
|
#ifdef DATAGEN
|
173 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
174 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
175 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
176 |
|
|
#else
|
177 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
178 |
|
|
// results.
|
179 |
|
|
printf("%d: 1/x=%f (%f)\n", x1, z2/MUL, (double)y1/x1);
|
180 |
|
|
#endif
|
181 |
|
|
}
|
182 |
|
|
|
183 |
|
|
// HYPERBOLIC, VECTORING, SQUARE ROOT + LINEAR, VECTORING, RECIPROCAL
|
184 |
|
|
#ifndef DATAGEN
|
185 |
|
|
printf("\nINVERSE SQUARE ROOT\n");
|
186 |
|
|
#endif
|
187 |
|
|
for (w1 = 4000; w1 <= 28600; w1+=200)
|
188 |
|
|
{
|
189 |
|
|
gdirection = VECTORING; gmode = HYPERBOLIC;
|
190 |
|
|
z1 = 0;
|
191 |
|
|
x1 = w1+(1<<12);
|
192 |
|
|
y1 = w1-(1<<12);
|
193 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
194 |
|
|
#ifdef DATAGEN
|
195 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
196 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
197 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
198 |
|
|
#else
|
199 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
200 |
|
|
// results.
|
201 |
|
|
printf("%d: sqrt=%f (%f)\n", w1, (cordic_1Kp/MUL)*x2/MUL, sqrt((double)w1/MUL));
|
202 |
|
|
#endif
|
203 |
|
|
gdirection = VECTORING; gmode = LINEAR;
|
204 |
|
|
z1 = 0;
|
205 |
|
|
y1 = (1<<14);
|
206 |
|
|
x1 = (cordic_1Kp/MUL)*x2;
|
207 |
|
|
cordic(gdirection, gmode, x1, y1, z1, &x2, &y2, &z2);
|
208 |
|
|
#ifdef DATAGEN
|
209 |
|
|
// Use this to generate the "cordic_test_data.txt" reference vectors.
|
210 |
|
|
printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
|
211 |
|
|
gdirection, gmode, x1&0xffff, y1&0xffff, z1&0xffff, x2&0xffff, y2&0xffff, z2&0xffff);
|
212 |
|
|
#else
|
213 |
|
|
// Use this to compare floating-point (math.h) against CORDIC fixed-point
|
214 |
|
|
// results.
|
215 |
|
|
printf("%d: 1/sqrt(x)=%f (%f)\n", w1, z2/MUL, sqrt((double)MUL/w1));
|
216 |
|
|
#endif
|
217 |
|
|
}
|
218 |
|
|
return (0);
|
219 |
|
|
}
|