Why we use CORDIC gain?

641 Views Asked by At

I'm studying the cordic. And I found the cordic gain. K=0.607XXX.

From CORDIC, K_i = cos(tan^-1(2^i)).

As I know the K is approched 0.607xxx.when I is going to infinity

this value come up with from all K multiplying.

I understand the reason of exist each k. But I am curioused Where does it used ? Why we use that value K=0.607xx?

1

There are 1 best solutions below

0
On BEST ANSWER

The scale factor for the rotation mode of the circular variant of CORDIC can easily be established from first principles. The idea behind CORDIC is to take a point on the unit circle and rotate it, in steps, through the angle u whose sine and cosine we want to determine.

To that end we define a set of incremental angles a0, ..., an-1, such that ak = atan(0.5k). We sum these incremental angles appropriately into a partial sum of angles sk, such than sn ~= u. Let yk = cos(sk) and xk = sin(sk). If in a given step k we rotate by ak, we have

yk+1 = cos (sk+1) = cos (sk + ak)
xk+1 = sin (sk+1) = sin (sk + ak)

we can compute xk+1 and yk+1 from xk and yk as follows:

yk+1 = yk * cos (ak) - xk * sin (ak)
xk+1 = xk * cos (ak) + yk * sin (ak)

Considering that we may both add and subtract ak, and that tan(ak) = sin(ak)/cos(ak), we get:

yk+1 = cos (ak) * (yk ∓ xk * tan(ak)) = cos (sk+1)
xk+1 = cos (ak) * (xk ± yk * tan(ak)) = sin (sk+1)

To simplify this computation, we can leave out the multiplication with cos(ak) in every step, which gives us our CORDIC iteration scheme:

yk+1 = y ∓ xk * tan(ak)
xk+1 = x ± yk * tan(ak)

Because of our choice of ak, the multiplications with tan(ak) turn into simple right shifts if we compute in fixed-point arithmetic. Because we left off the factors cos(ak), we wind up with

yn ~= cos(u) * (1 / (cos (a0) * cos (a1) * ... * cos (an))
xn ~= sin(u) * (1 / (cos (a0) * cos (a1) * ... * cos (an))

The factor f = cos (a0) * cos (a1) * ... * cos (an) is 0.607..., as already noted. We incorporate it into the computation by setting the starting values

y0 = f * cos(0) = f
x0 = f * sin(0) = 0

Here is C code that shows the entire computation in action, using 16-bit fixed-point arithmetic. Input angles are scaled such that 360 degrees correspond to 216, while sine and cosine outputs are scaled such that 1 corresponds to 215.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* round (atand (0.5**i) * 65536/360) */
static const short a[15] = 
{
    0x2000, 0x12e4, 0x09fb, 0x0511, 
    0x028b, 0x0146, 0x00a3, 0x0051, 
    0x0029, 0x0014, 0x000a, 0x0005, 
    0x0003, 0x0001, 0x0001
};

#define swap(a,b){a=a^b; b=b^a; a=a^b;}

void cordic (unsigned short u, short *s, short *c)
{
    short x, y, oldx, oldy, q;
    int i;

    x = 0;
    y = 0x4dba;  /* 0.60725 */
    oldx = x;
    oldy = y;

    q = u >> 14;    /* quadrant */
    u = u & 0x3fff; /* reduced angle */
    u = -(short)u;

    i = 0;
    do {
        if ((short)u < 0) {
            x = x + oldy;
            y = y - oldx;
            u = u + a[i];
        } else {
            x = x - oldy;
            y = y + oldx;
            u = u - a[i];
        }
        oldx = x;
        oldy = y;
        i++;
        /* right shift of signed negative number implementation defined in C */
        oldx = (oldx < 0) ? (-((-oldx) >> i)) : (oldx >> i);
        oldy = (oldy < 0) ? (-((-oldy) >> i)) : (oldy >> i);
    } while (i < 15);

    for (i = 0; i < q; i++) {
        swap (x, y);
        y = -y;
    }

    *s = x;
    *c = y;
}

int main (void)
{
    float angle;
    unsigned short u;
    short s, c;

    printf ("angle in degrees [0,360): ");
    scanf ("%f", &angle);
    u = (unsigned short)(angle * 65536.0f / 360.0f + 0.5f);
    cordic (u, &s, &c);
    printf ("sin = % f  (ref: % f)  cos = % f (ref: % f)\n",
            s/32768.0f, sinf(angle/360*2*3.14159265f), 
            c/32768.0f, cosf(angle/360*2*3.14159265f));
    return EXIT_SUCCESS;
}