CORDIC算法的来历与用途大家网上随处可以见到,这里写 一下自己的理解。
将P(x,y)旋转角度a得到新的坐标P’(x’,y’)。这里的坐标变换为:
x’= x cos(a) – y sin(a) = cos(a)(x-y *tan(a))
y’= y cos(a) + xsin(a) = cos(a)(y+x*tan(a))
旋转角度a为常数时,如果tan(a)=2-i ,即可用移位代替乘法便于快速高效在FPGA中实现。每次都旋转固定角度delta, 则cos(delta)=cos(arctan(2-i)).
而
从而得到简便计算如下:atan(2^-i)的结果是预先计算好存储下来了
Ki=cos(arctan(2-i))
Xi+1 =ki [xi – yi x di x 2-i]
Yi+1 =Ki [yI + XI x dix 2-i]
CORDIC有两种模式
1 rotation模式 每次旋转Z一个角度 直到等于要求的角度 即从极坐标变换到直角坐标
2 vectoring 模式 。旋转使与x轴对齐 y=0时得到的z值即所要旋转的角度,由直角坐标到极坐标的变换
CORDIC算法实现极坐标(polar)到直角坐标系(Cartesian)的变换。
1: function [horizonal,vertical]=polar2car(mag, pha);
2: x =mag; %令变量x等于极坐标的幅度,在直角坐标中y分量等于零,使其旋转角度pha,得到的分量即是得到在
3: y =0; %直角坐标系里的坐标
4: z=pha;
5: d=0;
6: i=0;
7: k = 0.6073; %K 增益
8: x = k*x;
9: while i<50
10: if z<0 d =-1;
11: else d = 1;
12: end
13: xNew=x-y*d*(2^(-i));
14: y=y+x*d*(2^(-i));
15: z=z-d*atan(1/2^(i));
16: i=i+1;
17:
18:
19: x=xNew;
20: end
21: horizonal = x;
22: vertical = y;
CORDIC算法实现直角坐标到极坐标系的变换。
function [mag, pha]= car2polar(x,y); %y =0;
%将直角坐标系中的点(x,y)旋转到x轴,旋转的角度即为其极坐标的相位,在x轴的长度等于极坐标的幅度
d=0; %可用于求相位,幅度
i=0;
z=0;
k = 0.6073; %K 增益 while i<50
if y<0 d = 1;
else d = -1;
end
xNew=x-y*d*(2^(-i));
y=y+x*d*(2^(-i));
z=z-d*atan(1/2^(i));
i=i+1; x=xNew;
end
x = x*k;
mag=x;
pha=z;
验证:
[a,b]= polar2car( 1,pi/3)
a =
0.5000
b =
0.8661
[a,b]= car2polar( 0.5000, 0.8661)
a =
1.0001
b =
1.0472
计算正切值atan只需将直角坐标变换为极坐标的程序中取出最后的角度值,即可得到反正切值。
function [ pha]= cordic_arcsin(c); %y =0;
%将点(1,0)旋转至其纵坐标=c,旋转的角度为角度 求反余弦也是同样道理
d=0;
i=0;
z=0;
x=1;
y=0;
k = 0.6073; %K 增益
xNew = x* k;
while i<100
if y<=c d = 1;
else d = -1;
end
x =xNew-y*d*(2^(-i));
y=y+xNew*d*(2^(-i));
z=z+d*atan(1/2^(i));
i=i+1; xNew=x;
end %mag=x;
pha=z;
function [pha]= cordic_arccos(c); %y =0;
d=0;
i=0;
z=0;
x=1;
y=0;
k = 0.6073; %K 增益
xNew = x* k;
while i<100
if x>=c d = 1;
else d = -1;
end
x =xNew-y*d*(2^(-i));
y=y+xNew*d*(2^(-i));
z=z+d*atan(1/2^(i));
i=i+1; xNew=x;
end %mag=x;
pha=z;
function [ pha]= cordic_arctan(x,y); %y =0;
%将点(x,y)旋转到x轴所需要的角度
d=0;
i=0;
z=0;
k = 0.6073; %K 增益
x = x*k;
while i<50
if y<0 d = 1;
else d = -1;
end
xNew=x-y*d*(2^(-i));
y=y+x*d*(2^(-i));
z=z-d*atan(1/2^(i));
i=i+1; x=xNew;
end %mag=x;
pha=z;
function [sine,cosine] = cordic_sine(angle);
% Initialitation
%%angle=30 ;
x = 1;
y = 0;
z = angle;
d = 1; i = 0; % Iterative factor
k = 0.6073; %K Factor
xNew = k*x;
while i < 50
if z <=0 d =-1;
else d = 1;
end
x= xNew -d*y*2^(-i);
y=y+d*xNew*2^(-i);
z=z-d*atan(2^(-i));
i=i+1;
xNew=x;
end
cosine = x
sine = y