Trig-functions with CORDIC

We've already described the CORDIC procedure for computing of the arctan-function. Instead of rotating the vector towards angle zero, try to reach a certain angle alpha. After the process the real argument will hold the cosine and the imaginary argument will give the sine of the angle alpha. Of course the arguments have to be devided by the CORDIC-gain. Note that the sine and cosine are calculated at the same time. Here the legOS routines:

/*The trig-functions sine, cosine, tan, atan*/
#include <conio.h>
#include <unistd.h>
#include <dbutton.h>
#include <dkey.h>
#define CORDIC_gain 1.646760258
double Phase (int k) /*in degrees*/
{
   switch(k)
     {
        case 1:  return  45.0000000;
        case 2:  return  26.5650512;
        case 3:  return  14.0362435;
        case 4:  return  7.12501635;
        case 5:  return  3.57633437;
        case 6:  return  1.78991061;
        case 7:  return  0.89517371;
        case 8:  return  0.44761417;
        case 9:  return  0.22381050;
        case 10: return 0.11190568;
        case 11: return 0.05595289;
        case 12: return 0.02797645;
        case 13: return 0.01398823;
        case 14: return 0.00699411;
        case 15: return 0.00349706;
        case 16: return 0.00174853;
        case 17: return 0.00087426;
        case 18: return 0.00043713;
        case 19: return 0.00021857;
        case 20: return 0.00010928;
        case 21: return 0.00005464;
        case 22: return 0.00002732;
        case 23: return 0.00001366;
        case 24: return 0.00000683;
        case 25: return 0.00000341;
        case 26: return 0.00000177;
        case 27: return 0.00000085;
        case 28: return 0.00000042;
        case 29: return 0.00000021;
        case 30: return 0.00000010;
        case 31: return 0.00000005;
        case 32: return 0.00000002;
        case 33: return 0.00000001;
     default: return 888;
     }
}
double trig(double alpha,int idx)
{  double a=1;
    double b=0;
    double kL=1;
    double Theta=0;
    double Temp,beta,tan;
     int L,sign,c;
  beta=alpha;
  c=0;
  while(beta>180) beta-=360; /*beta must be smaller than 180 */
  while(beta<-180) beta+=360; /*beta must be greater than -180 */
  if(beta>90 ) { beta=180-beta; c=1;} /*quadrant II */
  if(beta<-90) { beta=-beta-180; c=1;} /*quadrant III */
   
   for(L=1;L<34;L++)
      {
         if(Theta<beta) { sign=1; }  else { sign=-1; }
         Theta+=sign*Phase(L);
         Temp=a; 
         a-=b*kL*sign; 
         b+=Temp*kL*sign;
         kL/=2;
      }
    a/=CORDIC_gain;  /*a=cos(alpha)*/
    b/=CORDIC_gain; /*b=sin(alpha)*/
    if(c==1) a=-a;
    if(a!=0) {tan=b/a;} else { if(b>0) {tan=999999;} else {tan=-999999;} }
    switch(idx)
          {
             case 1: return a;  /*give the cosine */
             case 2: return b; /* give the sine */
             case 3: return tan;  /*give the tan */
           default: return 888;
           }
}
double atan(double x)
{  double a,b,Temp;
    double kL=1;
    double Theta=90;
    int L,sign;
  if(x>0) {b=1;} else {b=-1;}
  Theta*=-b; /*starting value +90 or -90 depending sign of x*/
  a=x*b; /*a will always be positive */
  Temp=a; /*now rotate by +/- 90; this could be done more quickly, but for better understanding*/
  a=b*b;
  b=-Temp*b; 
   
   for(L=1;L<34;L++)
      {
         if(b>0) { sign=-1; }  else { sign=1; }
         Theta+=sign*Phase(L);
         Temp=a; 
         a-=b*kL*sign; 
         b+=Temp*kL*sign;
         kL/=2;
      }
  if(x>0) { return Theta+90;} else {return Theta-90;}
}

int main()
{
   int j;  /*This is only test program*/
   int p;
   for (j=-10;j<11;j++)
     {
       cputs("x");
       sleep(1);
       lcd_int(j);
       sleep(1);
       cputs("atan");
       sleep(1);
       p=atan(j);
       lcd_int(p);
                             
        while(RELEASED(dbutton(),BUTTON_VIEW)); /*wait until view-button pressed*/
    }
   return 0;
}

 


RetourMain Page