Why we use CORDIC gain?

617 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 answers

0
njuffa 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;
}