// HP35601A test program
// GPIB ADDR #15 (HP35601A)
// Dr. Simon Schroedle, Started: Jan 18, 2014
//

#include "ni4882.h"

#include <time.h>
#include <stdlib.h>
#include <stdio.h>


#define M_E 2.71828182845904523536
#define M_LOG2E 1.44269504088896340736
#define M_LOG10E 0.434294481903251827651
#define M_LN2 0.693147180559945309417
#define M_LN10 2.30258509299404568402
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#define M_PI_4 0.785398163397448309616
#define M_1_PI 0.318309886183790671538
#define M_2_PI 0.636619772367581343076
#define M_1_SQRTPI 0.564189583547756286948
#define M_2_SQRTPI 1.12837916709551257390
#define M_SQRT2 1.41421356237309504880
#define M_SQRT_2 0.707106781186547524401


int Device35601 = 0;                   /* Device unit descriptor                  */
int Device3585 = 0;                   /* Device unit descriptor                  */
int Device3562 = 0;                   /* Device unit descriptor                  */

int   PrimaryAddress3562 = 12;      /* Primary address of the device           */
int   SecondaryAddress3562 = 0;    /* Secondary address of the device         */

int   PrimaryAddress35601 = 15;      /* Primary address of the device           */
int   SecondaryAddress35601 = 0;    /* Secondary address of the device         */

int   PrimaryAddress3585 = 11;      /* Primary address of the device           */
int   SecondaryAddress3585 = 0;    /* Secondary address of the device         */

int BoardIndex = 0;               /* Interface Index (GPIB0=0,GPIB1=1,etc.)  */


void GpibError(const char * msg); /* Error function declaration              */


double tracedata[14][1020]; //final data to plot
double traceparameters[30]; //various parameters of trace
char tracetexts[10][40]; //various trace texts

char caltexts[10][40]; //various cal text
double calparameters[30]; //various parameters that are not cal constants
double Caldata[8][6]; //current cal data

int P82_C[11][1012]; //first 10 segments, 1 to 10 is used, segment 0 unused
int P85_C[14][1012]; //correction offsets calculated by Phioffs

int P82[11][1012]; //first 10 segments, 1 to 10 is used, segment 0 unused
int P85[14][1012];
//sements 11 to 13; -4 to 1000 index;
//original index "-3" P85[][1007] is valid data flag, 0:invalid; 1: valid
//original index "-2" P85[][1008] stopbin
//original index "-1" P85[][1009] startbin
//original index "0" P85[][1010] Hzpbin (/250, *10)

double fac[]={1.0,10.0,100.0,1000.0,10000,100000,
              1000000,
              10000000,
              100000000,
              1000000000,
              10000000000,
              100000000000,
              1000000000000,
              10000000000000,
              100000000000000,
              1000000000000000};

double FROUND(double x, unsigned int digits) {  //round t a fixed number of decimals
    return round(x*fac[digits])/fac[digits];
}

double frand(void)
{
    return ((float)rand()/((float)(RAND_MAX)+1.0));
}

double FNPround(double Xi,double Round)
{
    double X,Det,Y;
    X=Xi;

    if (Round>0)
    {
       X=trunc(X);
       Det=fmod(X,pow(10,Round));
       X=trunc(X / pow(10,Round));
       X=X*pow(10,Round);
       if (Det>=(5*pow(10,(Round-1)))) { X=X+(1*pow(10,Round));}
    }
    if (Round==0)
    {
       Det=fmod(X,1);
       X=trunc(X);
       if ((Det*10)>=5) { X=X+1;}
    }
    if (Round<0)
    {
       Y=fmod(X,1);
       X=trunc(X);
       Y=Y/pow(10,Round);
       Det=fmod(Y,1);
       Y=trunc(Y);
       if (Det>=0.5) {Y=Y+1;}
       X=X+(Y*pow(10,Round));
    }
   return X;
}


double FNMax(double a1, double a2) //return max value of set of values
{
    double t;
    t=a1;
    if (a2>a1) {t=a2;}
    return t;
}

double FNMin(double a0, double a1) //return min value of set of values
{
    double t;
    t=a0;
    if (a1<t) {t=a1;}
    return t;
}



double fsgn(double t) //return sign of double number
{
    if (t<0) {return -1.0;}
    if (t>0) {return 1.0;}
    if (t==0) {return 0.0;}
}


double DROUND(double num, int n) { //round to a fixed number of significant digits
    double d,magnitude;
    int power;
    long shifted;


    if(num == 0) {
        return 0;
    }

    d = ceil(log10(num < 0 ? -num: num));
    power = n - (int) d;

    magnitude = pow(10, power);
    shifted = round(num*magnitude);
    return shifted/magnitude;
}


char latchd[20]={0,0x80,1,0x80,2,0x80,3,0x80,4,0x80,5,0x80,6,0x80,7,0x80,8,0x80,9,0x80};
//latch data latchd[0]=latch 0 latchd[1]=bit latch 0 usw., 0x80 set indicates bit data, 0x80 clear latch select

void zerolatch(void)//preset 35601 latches
{
    int i;
    for (i=1;i<20;i=i+2)
    {
        latchd[i]=0x80;
    }
}


void writelatch(void)
{
      ibwrt(Device35601, latchd, 20); //write all latch data
   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}

void CError(const char *msg)   //error handler for 35601A unknown command
{
    printf("\n!! Command error: %s\n",msg);
    exit(1);
}

void PError(const char *msg)   //error handler for incorrect parameter
{
    printf("\n!! Parameter error: %s\n",msg);
    exit(1);
}

/*
 ! RELAY  LATCH  LATCH  0,1
18560   !          #     BIT
18570   !  K1      2      3    INPUT TO FILTERS, AMP
18580   !  K2      1      6    CAL ON
18590   !  K3      1      2    TG TO CAL PATH
18600   !  K4      1      2    SAME AS K3
18610   !  K5      0      5    ARMSTRONG OFF, TG ON
18620   !  K6      0      3    TG TO PLL
18630   !  K7      0      7    TG ON
18640   !  K8      4      7    2MHZ LF FILTER
18650   !  K9      4      7    SAME AS K8
18660   !  K10     4      3    SIGNAL TO PLL CKTS
18670   !  K11     2      7    AMP IN
18680   !  K12     2      5    FILTERS, AMP TO OUTPUT
18690   !  K13     1      4    1.5 GHZ MIXER, 18 GHZ MIXER
18700   !  K14     2      7    SAME AS K11
18710   ! ------------------------
18720   ! SWITCH  LATCH  LATCH
18730   !           #     BIT
18740   !  S1       9      6   3582A NOISE SOURCE TO SUM
18750   !  S2       1      1   TRACKING GEN TO SUM AMP
18760   !  S3       0      4   PLL CLOSED
18770   !  S4       0      6   SEARCH ON
18780   !  S5       2      6   SUM (xfer fn) TO 3582A
18790   !  S6       2      2   VCO CONTROL TO 3582A
18800   !  S7       3      1   X100 AMP TO 3582A
18810   !  S8       3      3   3585A 50 OHM TO 3582A
18820   ! -----------------------
18830   ! SWITCH  86  94
18840   !
18850   !  F0     0   0    100KHZ FILTER, LF BOARD
18860   !  F1     0   1    1KHZ FILTER
18870   !  F2     1   1    10HZ FILTER
18880   ! -----------------------
18890   ! SWITCH  LATCH  LATCH
18900   !           #     BIT
18910   !  L0       9      3   3582 NOISE INTO CHAN A
18920   !  L1       8      5   HF BOARD INTO LF BOARD
18930   !  L2       8      7   AC COUPLING
18940   !  L3       7      5   AC/DC FROM HF BOARD INTO CHANNEL B
18950   !  L4       7      1   LF PM X5 INTO CHANNEL B
18960   !  L5       9      5   LF PM X20 INTO CHANNEL B (ACTIVE LOW)
18970   !  L6       7      4   LF AM X5 INTO CHANNEL B
18980   !  L7       9      1   LF AM X5 INTO CHANNEL B
18990   !  L8       7      2   LF AM X20 INTO CHANNEL A
19000   !  L9       7      6   HF LOCK/OVERLOAD MONITOR INTO CHAN A
19010   !  L10      7      3   LF AM X20 INTO X5
19020   !  L11      8      3   LF 0=BANDPASS FILTER, 1=X2.5 AMP
19030   !  L12      9      2   LF PM X20 TO PHASE LOCK CONTROL
19040   !  L13      8      4   LF 0=EXTERNAL 10 MHZ, 1=VCXO TO SYNTH
19050   !  L14      8      1   LF SYNTH CONTROL 0=370 KHZ, 1=350 KHZ
19060   !  L15      8      2   LF PHASE LOCK CTRL 0=ADAPT, 1=WIDEBND
19070   !  L16      7      7   LF 3582 NOISE INTO PM X20
19080   !  L17      6      7   ARMSTRONG AM MODULATED
19090   !  L18      6      6   ARMSTRONG PM MODULATED
19100   !  L19      0      1   10 MHZ TO ARMSTRONG MODULATOR
19110   !  L20      0      2   10 MHZ TO LF BOARD
19120   !  L21      3      2   LF PHASE LOCK CTRL, 0=ADAPT,1=N BAND
19130   ! -----------------------
*/

const char k_v[40]={0,0,2,3,1,6,1,2,1,2,0,5,0,3,0,7,4,7,4,7,4,3,2,7,2,5,1,4,2,7,0,9,0,9,0,9,0,9,0,9};
const char s_v[20]={0,9,9,6,1,1,0,4,0,6,2,6,2,2,3,1,3,3,0,9};
//const char f_v[20]={8,6,9,4,9,4,0,9,0,9,0,9,0,9,0,9,0,9,0,9};
const char l_v[44]={9,3,8,5,8,7,7,5,7,1,9,5,7,4,9,1,7,2,7,6,7,3,8,3,9,2,8,4,8,1,8,2,7,7,6,7,6,6,0,1,0,2,3,2};


/*
22050   ! DAC   LATCH  LATCH
22060   ! BITS    #     BIT
22070   !  0      5      1
22080   !  1      4      5
22090   !  2      4      6
22100   !  3      4      4
22110   !  4      5      3
22120   !  5      5      5
22130   !  6      5      4
22140   !  7      5      2
22150   ! POS DAC 3      7
22160   ! NEG DAC 4      2
22170   ! ----------------
22180   ! GAIN1
22190   ! BIT
22200   !  0      5      7  4 dB STEPS
22210   !  1      5      6
22220   !  2      6      2
22230   ! ----------------
22240   ! GAIN2
22250   ! BIT
22260   !  0      6      1  2 dB STEPS
22270   !  1      6      4
22280   !  2      6      3
22290   ! ----------------
22300   ! LEAD LAG
22310   ! BIT
22320   !  0      3      6
22330   !  1      6      5
22340   !  2      9      7
22350   ! ----------------
22360   ! ATTEN1
22370   ! BIT
22380   !  0      1      7  x.1 0 dB
22390   !  1      2      4  x.2 6 dB
22400   !  2      1      5  x.5 14 dB
22410   !  3      1      3  x1  20 dB
22420   ! ----------------
22430   ! ATTEN2
22440   ! BIT
22450   !  0      3      4  x.5 6 dB (1),x1 0 dB (0)
22460   ! ----------------
*/

const char dac_v[16]={5,1,4,5,4,6,4,4,5,3,5,5,5,4,5,2}; //bits 0 to 7
const char dacpos_v[2]={3,7};
const char dacneg_v[2]={4,2};

const char gain1_v[6]={5,7,5,6,6,2}; // 4 db steps,0 to 28 db (7*4db=28) ; bits 0 to 2, same for others
const char gain2_v[6]={6,1,6,4,6,3}; // 2 db steps, 6 to 20 db  (7*2db=14db, 14db+6db=20db)

const char leadlag_v[6]={3,6,6,5,9,7};

const char atten1_v[8]={1,7,2,4,1,5,1,3}; //.1, .2, .5, 1 ; 4 steps; 0/6/14/20 valid numbers (dB)
const char atten2_v[2]={3,4}; //set: .5, clear:1.;  2 steps; 0/6 valid numbers (dB)


#define NOCOMMAND 0 //writes latch, but no command.
#define OVERLOAD 1
#define OUTOFLOCK 2
#define TOGGLEACDC 3

const char delimiters[] = " ,;:"; //command delimiters; use "," as default

static char token_s[255]; //just in case if needed for some error handling
static char cp_s[255];

void setup_i(const char *commands)
{
   int  k_nr,tcnt;
   char  tc,clearl;
   char *token;
   char *cp;

   cp=cp_s;
   token=token_s;
   strcpy(cp,commands);

//   printf("command length: %i\n",strlen(cp));

   token = strtok (cp, delimiters);
   tcnt=0; //count tokens
   do
   {
     tcnt++;
     //printf("%i >%s<\n",tcnt,token);
     tc=token[0];
     if (tc==45) { clearl=1; } else{ clearl=0;}
     tc=token[clearl];
     if (tc=='K') //handle relais
     { k_nr=atoi(token+1+clearl);
         if ((k_nr>0)&&(k_nr<15))
         {
             if (clearl)
             { latchd[(k_v[k_nr<<1]<<1)+1] &= ~(1<<(k_v[(k_nr<<1) + 1]-1));}
             else
             { latchd[(k_v[k_nr<<1]<<1)+1] |= 1<<(k_v[(k_nr<<1) + 1]-1); }
         }   else { CError(token); }
     } else
     if (tc=='S')
     { k_nr=atoi(token+1+clearl);
         if ((k_nr>0)&&(k_nr<9))
         { if (clearl)
             { latchd[(s_v[k_nr<<1]<<1)+1] &= ~(1<<(s_v[(k_nr<<1) + 1]-1));}
             else
             {latchd[(s_v[k_nr<<1]<<1)+1] |= 1<<(s_v[(k_nr<<1) + 1]-1);}
         }   else { CError(token); }
     } else
     if (tc=='F')
     {
       k_nr=atoi(token+1);
         if ((k_nr>=0)&&(k_nr<3))
         {
           if (k_nr==0) //100 khz
           {
             latchd[(8<<1)+1] &= ~(1<<(6-1));  // latch 8 bit 6
             latchd[(9<<1)+1] &= ~(1<<(4-1));  // latch 9 bit 4
             printf("LPF set to 100 kHz.\n");
           }
           if (k_nr==1) //1 khz
           {
             latchd[(8<<1)+1] &= ~(1<<(6-1));
             latchd[(9<<1)+1] |= (1<<(4-1));
             printf("LPF set to 1 kHz.\n");
           }
           if (k_nr==2) //10 hz
           {
             latchd[(8<<1)+1] |= (1<<(6-1));
             latchd[(9<<1)+1] |= (1<<(4-1));
             printf("LPF set to 10 Hz.\n");
           }
         }   else { CError(token); }

     } else
     if (tc=='L')
     { k_nr=atoi(token+1+clearl);
         if ((k_nr>=0)&&(k_nr<22))
         { if (clearl)
             { latchd[(l_v[k_nr<<1]<<1)+1] &= ~(1<<(l_v[(k_nr<<1) + 1]-1));}
             else
             {latchd[(l_v[k_nr<<1]<<1)+1] |= 1<<(l_v[(k_nr<<1) + 1]-1);}
         }   else { CError(token); }
     } else {CError(token);}

     token = strtok (NULL, delimiters);
   } while (token!=NULL);

   writelatch();  //latch setzen
}

void toggle_i(int codei)
{
   switch (codei)
   {
     case NOCOMMAND:
         writelatch();
         break;
     case OVERLOAD:
        latchd[9] |= 0x01; //overload
        writelatch();
        latchd[9] &= ~(0x01);
        writelatch();
        //printf("overload reset OK\n");
        break;
     case OUTOFLOCK:
        latchd[7] |= 0x10; //out of lock
        writelatch();
        latchd[7] &= ~(0x10);
        writelatch();
        //printf("out of lock reset OK\n");
        break;
     case TOGGLEACDC:
        setup_i("-L2");
        setup_i("L2");
        wait_s01(5);
        break;

     default:
        CError("Invalid TOGGLE command.");
    }
}


#define NOVALUE     0x00 //updates latch from valued and sets latch
#define DAC         0x01
#define DACPOS      0x02
#define DACNEG      0x03
#define GAIN1       0x04
#define GAIN2       0x05
#define LEADLAG     0x06
#define ATTEN1      0x07
#define ATTEN2      0x08

char valued[9]={0,0,0,0,0,0,0,0,0}; //BIT data: empty, DAC, pos, neg, GAIN1, GAIN2, LEADLAG, ATTEN1, ATTEN2

void value_i(int codei,double valuei)
{
   int c_t;
   int i_t;
   double value_t;

   switch (codei)
   {
     case NOVALUE:
        break;
     case DAC:
        value_t=valuei/0.045; //convert 11.475 Volt to 8 bit, resolution about 0.045 V
        if (value_t>=0) {i_t=(int)value_t;valued[DACPOS]=1;valued[DACNEG]=0;}
          else {i_t=(int)(-1*value_t); valued[DACPOS]=0;valued[DACNEG]=1;}
        if ((i_t>=0)&&(i_t<256))
            { valued[DAC]=i_t;
              //printf("\n dac value: %i\n",i_t);
            } else {CError("Invalid DAC value");}

        break;
     case GAIN1: //0 to 28 db in 4 db steps
        i_t=(int) valuei;
        //printf("Gain1 %i",i_t);
        i_t=(i_t>>2)<<2; //make sure it is 4 db steps
        //printf("Gain1 v %i",i_t);

        if ((i_t>=0)&&(i_t<=28))
            { valued[GAIN1]=i_t;  //printf("\n GAIN1 value: %i\n",i_t);
            } else {CError("Invalid GAIN1 value");}

        break;
     case GAIN2: //6 to 20 in 2 db steps
        i_t=(int) valuei;
        i_t=(i_t>>1)<<1; //make sure it is 2 db steps

        if ((i_t>=6)&&(i_t<=20))
            { valued[GAIN2]=i_t;  //printf("\n GAIN2 value: %i\n",i_t);
            } else {CError("Invalid GAIN2 value");}

        break;
     case LEADLAG: //0 to 7
        i_t=(int) valuei;
        if ((i_t>=0)&&(i_t<=7))
            { valued[LEADLAG]=i_t;  //printf("\n LEADLAG value: %i\n",i_t);
            } else {CError("Invalid LEADLAG value");}

        break;
     case ATTEN1:
        i_t=(int) valuei;
        if ((i_t!=0)&&(i_t!=6)&&(i_t!=14)&&(i_t!=20)) {CError("Invalid ATTEN1 value");}
        valued[ATTEN1]=i_t;
        break;
     case ATTEN2:
        i_t=(int) valuei;
        if ((i_t!=0)&&(i_t!=6)) {CError("Invalid ATTEN2 value");}
        valued[ATTEN2]=i_t;
        break;
     default:
        CError("Invalid VALUE command.");
    }


    //set latch values based  on valuei data
    //DAC
    for (c_t=0;c_t<8;c_t++)
    {
      if ((valued[DAC]>>c_t)&0x01)
             {latchd[(dac_v[c_t<<1]<<1)+1] |= 1<<(dac_v[(c_t<<1) + 1]-1);
               //printf("value: %i, bit %i set\n",valued[DAC],c_t+1);
             }
             else
             {latchd[(dac_v[c_t<<1]<<1)+1] &= ~(1<<(dac_v[(c_t<<1) + 1]-1));}

    }
    if (valued[DACPOS]==0x01)
             { //printf("POSX %x\n",latchd[7]);
               latchd[(dacpos_v[0]<<1)+1] |= 1<<(dacpos_v[1]-1);
               //printf("POSY %x\n",latchd[7]);
               }
             else
             {latchd[(dacpos_v[0]<<1)+1] &= ~(1<<(dacpos_v[1]-1));}
    if (valued[DACNEG]==0x01)
             { //printf("NEGX %x\n",latchd[9]);
             latchd[(dacneg_v[0]<<1)+1] |= 1<<(dacneg_v[1]-1); //  printf("NEGY %x\n",latchd[9]);
             }
             else
             {latchd[(dacneg_v[0]<<1)+1] &= ~(1<<(dacneg_v[1]-1));}
    //GAIN1
    for (c_t=0;c_t<3;c_t++)
    {
      if ((valued[GAIN1]>>(c_t+2))&0x01)
             {latchd[(gain1_v[c_t<<1]<<1)+1] |= 1<<(gain1_v[(c_t<<1) + 1]-1);}
             else
             {latchd[(gain1_v[c_t<<1]<<1)+1] &= ~(1<<(gain1_v[(c_t<<1) + 1]-1));}
    }
   //GAIN2
    for (c_t=0;c_t<3;c_t++)
    {
      if (((valued[GAIN2]-6)>>(c_t+1))&0x01)
             {latchd[(gain2_v[c_t<<1]<<1)+1] |= 1<<(gain2_v[(c_t<<1) + 1]-1);}
             else
             {latchd[(gain2_v[c_t<<1]<<1)+1] &= ~(1<<(gain2_v[(c_t<<1) + 1]-1));}
    }
    //leadlag
    for (c_t=0;c_t<3;c_t++)
    {
      if ((valued[LEADLAG]>>c_t)&0x01)
             {latchd[(leadlag_v[c_t<<1]<<1)+1] |= 1<<(leadlag_v[(c_t<<1) + 1]-1);}
             else
             {latchd[(leadlag_v[c_t<<1]<<1)+1] &= ~(1<<(leadlag_v[(c_t<<1) + 1]-1));}
    }
    //ATTEN1
    if (valued[ATTEN1]==20) { latchd[(atten1_v[0]<<1)+1] |= 1<<(atten1_v[1]-1); }
             else {latchd[(atten1_v[0]<<1)+1] &= ~(1<<(atten1_v[1]-1));}
    if (valued[ATTEN1]==14) { latchd[(atten1_v[2]<<1)+1] |= 1<<(atten1_v[3]-1); }
             else {latchd[(atten1_v[2]<<1)+1] &= ~(1<<(atten1_v[3]-1));}
    if (valued[ATTEN1]==6) { latchd[(atten1_v[4]<<1)+1] |= 1<<(atten1_v[5]-1); }
             else {latchd[(atten1_v[4]<<1)+1] &= ~(1<<(atten1_v[5]-1));}
    if (valued[ATTEN1]==0) { latchd[(atten1_v[6]<<1)+1] |= 1<<(atten1_v[7]-1); }
             else {latchd[(atten1_v[6]<<1)+1] &= ~(1<<(atten1_v[7]-1));}


    //ATTEN2
    if (valued[ATTEN2]==6) { latchd[(atten2_v[0]<<1)+1] |= 1<<(atten2_v[1]-1); }
             else {latchd[(atten2_v[0]<<1)+1] &= ~(1<<(atten2_v[1]-1));}

    writelatch(); //write all latch data to hp35601a
}



void print_i_setup(void)
{
    double dacv;

    printf("\nHP35601A Setup:\n");

    dacv=valued[DAC]*0.045;
    printf("\nDAC   ");
    if (valued[DACNEG]==1) {dacv=-dacv; printf("NEG");} else {printf("POS");}
    printf(" %3i %.3f V  (NEG/POS 0..255, -11.475..+11.475 V)\n",valued[DAC],dacv);

    printf("GAIN1      %2i dB (0-28 dB)\n",valued[GAIN1]);
    printf("GAIN2      %2i dB (6-20 dB)\n",valued[GAIN2]);
    printf("LEADLAG     %i (0-7)\n",valued[LEADLAG]);
    printf("ATTEN1     %2i (0/6/14/20 dB)\n",valued[ATTEN1]);
    printf("ATTEN2      %i (0/6 dB)\n",valued[ATTEN2]);
    printf("\n");
}


void wait_s01(int s01) //wait 100 ms intervals
{
  clock_t ticks1, ticks2;

  ticks1=clock();
  ticks2=ticks1;
  while((ticks2/(CLOCKS_PER_SEC/10)-ticks1/(CLOCKS_PER_SEC/10))<s01)
    ticks2=clock();
}


int rangedbv;
int stat;

char  Buffer[10000];             /* Read buffer                             */

unsigned int Display3585[1002];




double Loopbw1,Loopbw3,W1,W2,W3;
double Loopbw1_actual;
double Vcofreq,Spec,Vcoindex;
double Laglead;
double Zerofreq[]={9.95,40.1,115.9,306,784,1.985E3,5E3,12.58E3,31612,79421,199511,501164};
      //         !Actual Leadfreqs for each lag-lead
          //     ! Plus 4 EXTERNAL lag-leads
double Laglead2; //               !Effective Lag-lead if external lag-lead used

double     C8=3.3E-8;               //  ! .033 uf
double     R25=4.823E+5;          //    ! 482K ohm


/*
10984   ! *  NAME: Fnw
10990   ! *  FUNCTION: Compute the xfer function value at W
10996   ! *  INPUT:  W, W1, W2, W3, Bw1
11002   ! *  OUTPUT: Returns the xfer funtion value
*/

double FNW(double W,double W1,double W2,double W3,double Bw1)
{
double Ang; //                    !Phase angle of loop correction
double Fw; //                     !F(w) -- loop correction factor
double Pole;
double R;//                      !Magnitude of loop correction
double Ww;//                     !W  squared
double Ww1;//                    !W1 squared
double Ww2;//                    !W2 squared
double Ww3;//                    !W3 squared

    Ww=W*W;
    Ww1=W1*W1*4.0;
    Ww2=W2*W2;
    Ww3=W3*W3;
//    ! W0=1/2
    R=2*M_PI*Bw1/W*sqrt((1+Ww/Ww2)*(1+0.25/Ww)/(1+Ww/Ww3)/(1+Ww/Ww1));
    Pole=W/1.75E+6;
    if (Pole>(M_PI/2.0)) {Pole=M_PI/2.0;}

    Ang=-atan(W/W1)+atan(W/W2)-atan(W/W3)-M_PI/2.0-atan(0.5/W)-Pole;
    Fw=-10*log10(1+2*R*cos(Ang)+R*R);

    return Fw;
}



/*
11080   ! *  NAME: Difcorrection
11086   ! *  FUNCTION: Use a differential correction technique to determine
11089   ! *            the correct values of W1 and Bw1 used by Fnw
11095   ! *  INPUT:  X(*), Y(*), W1, W2, W3, Bw1
11101   ! *  OUTPUT: W1, Bw1, Maxpointerror
*/


double X[1050],Y[1050];
double W1,W2,W3,Bw1;
double Maxpointerror;
double  Slope;

void Difcorrection(int N)
{
    double Sumslope;   //            !Sum of squares of slope
    double Sumfreq;    //            !Sum of freq correction needed
    double  Corr;      //            !Freq correction term
    double  Delta;     //            !Percent change to calculate derivitive
    double  Error;     //            !Current error for one point
    double Errsum;     //            !Sum of all errors
    double  Fw;        //            !F(w) -- loop correction factor
    double  Fwhigh;    //            !F(High)
    double  Fwlow;     //            !F(Low)
    double  High;      //            !Higher point in search check
    int I;            //             !For-next loop counter
    double  Loopbw3;  //             !Closed loop bandwidth
    int Loopcount;    //             !# of times correction loop is executed
    double  Low;      //             !Lower point in search check
// ! INTEGER N        //             !Number of data points to use in fit
    double  Oldersum; //             !Last Errsum value
    double  Peaking; //              !Amount of peaking in loop above predicted
    double  Span;   //               !Frequency range to search for peak
    double  W;      //               !Radial freq

//   ! Calculate initial guess for W1 by the amount of extra peaking needed
//11170    No_look=0 !SET TO 1 TO LOOK AT DEBUG
    Loopbw3=Bw1*W3/W2;
    Span=10.0*M_PI*Loopbw3;
    Low=0.318197*Span+M_PI*Loopbw3/2.0;
    High=0.61803*Span+M_PI*Loopbw3/2.0;
    Fwlow=FNW(Low,1.0E+7,W2,W3,Bw1);
    Fwhigh=FNW(High,1.0E+7,W2,W3,Bw1);

    for (Loopcount=1;Loopcount<=8;Loopcount++)
    {
       Span=Span*0.61803;
       if (Fwlow<Fwhigh)
       {
         Low=High;
         Fwlow=Fwhigh;
         High=Low+(0.61803-0.38197)*Span;
         Fwhigh=FNW(High,1.0E+7,W2,W3,Bw1);
       }
        else
       {
         High=Low;
         Fwhigh=Fwlow;
         Low=High-(0.61803-0.38197)*Span;
         Fwlow=FNW(Low,1.0E+7,W2,W3,Bw1);
       }
    }
    Peaking=Y[N]-Fwlow;
    W1=1.0E+7;
    if (Peaking>0) {W1=2*M_PI*Loopbw3*(-1.1+6.33/Peaking+0.195/(Peaking*Peaking));}
    W1=FNMax(W1,2*M_PI*Loopbw3);

    printf("EXTRA PEAKING=%e\n",Peaking);                     // ! DEL
    printf("INITIAL W1=%e\n",W1);                             // ! DEL
    printf("W2=%e  BW1=%e\n",W2,Bw1);                         // ! DEL

    Oldersum=0;
    Loopcount=0;

//11272 Loop:  !

    for (Loopcount=1;Loopcount<=10;Loopcount++)
    {
//     ! Compute correction for W1 -- user-pole-freq
       Errsum=0;
       Sumfreq=0;
       Sumslope=0;
       for (I=1;I<=N;I++)
       {
          W=X[I]*2.0*M_PI;
          Fw=FNW(W,W1,W2,W3,Bw1);
          Delta=0.015+0.01*frand();
          Slope=(FNW(W,W1+W1*Delta,W2,W3,Bw1)-Fw)/(W1*Delta);
          Error=Fw-Y[I];
          Errsum=Errsum+fabs(Error);
          Sumslope=Sumslope+Slope*Slope;
          Sumfreq=Sumfreq-Slope*Error;
       }

       if (Errsum<0.04) {Loopcount=999;} // ! Return if total error small

       if  (fabs(Oldersum-Errsum)<0.005) {Loopcount=999;}

    if (Loopcount<999)
    {
       Corr=Sumfreq/Sumslope;
       if (fabs(Corr)>W1) {Corr=fsgn(Corr)*W1/2.0;}
       W1=Corr+W1;

//     ! Compute correction for Bw1 -- open-loop-gain

       Maxpointerror=0;
       Errsum=0;
       Sumfreq=0;
       Sumslope=0;

       for (I=1;I<=N;I++)
       {
          W=X[I]*2*M_PI;
          Fw=FNW(W,W1,W2,W3,Bw1);
          Delta=0.015+0.01*frand();
          Slope=(FNW(W,W1,W2,W3,Bw1+Bw1*Delta)-Fw)/(Bw1*Delta);
          Error=Fw-Y[I];
          Maxpointerror=FNMax(Maxpointerror,fabs(Error));
          Errsum=Errsum+fabs(Error);
          Sumslope=Sumslope+Slope*Slope;
          Sumfreq=Sumfreq-Slope*Error;
        }
    }
       if (Errsum<0.04) {Loopcount=999;} // ! Return if total error small
    if (Loopcount<999)
    {
//     ! Only allow corrections that are less than 1/4 the current value
       Corr=Sumfreq/Sumslope;
       if (fabs(Corr)>(Bw1/4.0)) {Corr=Bw1/4.0*fsgn(Corr);}
       Bw1=Corr+Bw1;
       Oldersum=Errsum;
    }

    }//loopcount
//11422 Diffcorrret:      !

    printf("FINAL W1=%e\n",W1);//                ! DEL
    printf("MAX ERROR IN DIFCORRECTION IS: %e\n\n",Maxpointerror);  //  ! DEL

}


double W,W5;
/*
10783   ! *  FUNCTION: Given a frequency, and other inputs, calculate the
10786   ! *             correction factors needed.
10792   ! *  INPUT:  Amplifier, Vcoport, Mixerfreq, Caldata(*), W1, W2, W3,
10795   ! *          Loopbw1, Phaseslope, Vcoslope, F
10801   ! *  OUTPUT: Returns correction factor (Still needs Bandwidth and gain)
*/
double FNCalpoint(int Amplifier,int Vcoport,double Mixerfreq,double W1,double W2,double W3,double Loopbw1,double Phaseslope,double Vcoslope,double F)
{
    double Cal; //              !Total calibration for point
    int Calnum; //              !Index into Caldata(*) for coeffecients
    double C1,C2,C3,C4,C5; //   !Calibration coeffecients
    int I; //                   !Dummy variable in call to Getfreqparms
    int Index; //               !Measurement index where data point would have been taken


    Getfreqparms(F,F,&I,&Index);

    C1=0;
    C2=0;
    C3=0;
    C4=0;
    C5=0;
  if (!(Vcoport))
  {

    if (Mixerfreq<9.5E+7)
    {
        C1=Caldata[1][1];
        C2=Caldata[1][2];
        C3=Caldata[1][3];
        C4=Caldata[1][4];  // !NO C5 FOR FILTER
    }

    if (Amplifier!=0)
    {
         if (Index<=4)
         {
            C1=C1+Caldata[2][1]+Caldata[2][2]*40.0+Caldata[2][3]*1600.0+Caldata[2][4]*64000.0+Caldata[2][5]/40.0;

         }
            else
         {

            if (Index==13) {Calnum=5;}
            if (Index==12) {Calnum=4;}
            if (Index==11) {Calnum=4;}
            if (Index<=10) {Calnum=3;}
            if (Index<=6) {Calnum=2;}
            C1=C1+Caldata[Calnum][1];
            C2=C2+Caldata[Calnum][2];
            C3=C3+Caldata[Calnum][3];
            C4=C4+Caldata[Calnum][4];
            C5=C5+Caldata[Calnum][5];
         }
    }
    C1=C1+Caldata[7][1]+Caldata[6][1];
    if (Index>10)
    {
        C2=C2+Caldata[7][2]+Caldata[6][2];
        C3=C3+Caldata[7][3]+Caldata[6][3];
        C4=C4+Caldata[7][4]+Caldata[6][4];
        C5=C5+Caldata[7][5]+Caldata[6][5];
    }

  }

    Cal=C5/F+C1+F*(C2+F*(C3+F*C4));

    if (!((Phaseslope==0) & (Vcoslope==0)))
    {

       W5=2.0*M_PI*33500.0;
       W=2.0*M_PI*F;

//   ! IF PHASESLOPE=0 THEN THIS IS A DISCRIMINATOR MEASUREMENT
       if (Phaseslope==0)
       {
           Cal=Cal+20.0*log10(Vcoslope)-20.0*log10(F);
       }

       if (Vcoport & (Phaseslope!=0))
       {
           Cal=Cal+20.0*log10(Vcoslope)-20.0*log10(F)+10.0*log10((1+(W/W5)*(W/W5))*(1+(W/W2)*(W/W2))/(1+(W/W3)*(W/W3)));
       }

       if ((!Vcoport) & (Phaseslope!=0))
       {
           Cal=Cal-20.0*log10(Phaseslope)-FNW(W,W1,W2,W3,Loopbw1);
       }


       if (Index<=2) {Cal=Cal+10.0*log10(1+1/(W*W));}
//   ! NOTE: Cal still needs bandwidth and gain (if amp in) corrections
    }
    return Cal;
}

void w3585(char *buf)
{

   //printf("Command: >%s<\n",buf);
   //printf("Length: %i bytes\n",strlen(buf));
   ibwrt(Device3585, buf, strlen(buf)); //write all latch data


   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}

void w3585d(char *buf) //for debug only
{

    printf("Command: >%s<\n",buf);
    printf("Length: %i bytes\n",strlen(buf));
   ibwrt(Device3585, buf, strlen(buf)); //write all latch data


   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}

void r3585(int cnt)
{
   ibrd(Device3585, Buffer, cnt); //read

   if (Ibsta() & ERR) {
      GpibError("ibrd Error");
   }
}

void rd3585(void)
{
   unsigned char tbuf[2004];
   int i;

   ibrd(Device3585, tbuf, 2004); //read

   if (Ibsta() & ERR) {
      GpibError("ibrd Error");
   }
   for (i=0;i<=1002;i++)
   {
     Display3585[i]=(tbuf[2*i]<<8)+tbuf[2*i+1];
   }
}


void autorange85(void)
{
    char tbuf[10];
    int checkcount;
    int rangenum;

    printf("3585A: autorange85\n");

    w3585("RLDV AL0 AL1 SV4 R01");
    do
    {
        wait_s01(1);

        w3585("D6T4");
        r3585(2);
        stat=Buffer[0];
      //  printf("D6 Status: 0x%02X\n",stat&0xff);
    } while ((stat&0x03)==0x03);
    rangenum=0;
    do
    {
       rangenum++;
       sprintf(tbuf,"R%02d",rangenum);
       w3585(tbuf);
       toggle_i(OUTOFLOCK);
       checkcount=0;
       do {
        w3585("D6T4");
        r3585(2);
        stat=Buffer[0];
        checkcount++;
       } while (((stat&0x01)==0x01)&&(checkcount<51));
    }  while ( (rangenum<12) && ((stat&0x01)==0x01));
    rangedbv=rangenum*5-43;

    printf("rangenum: %d\n",rangenum);
    printf("rangedbv: %d\n",rangedbv);
}

double Approxfreq,Newfreq;

void getbeatnote(void)
{

int Binn;                //Binn number of beatnote
int Crossingcount;       //Number of zero crossings on 3582A display
int Endbinn;             //Binn # of last zero crossing
double Freq;                   //Freq of beatnote
int I;                   //For-next loop counter
int Lastbin;             //Bin number of latest zero crossing
int Maxx;                //Max of 3585A display, level needed
                               //  on 3582A time record to be valid
int Minn;                //Min level needed on 3582A time record
int Numcycles;           //Number of cycles on 3582A time record
int Order[4];               //The order in which freq spans are checked
int Rangenum;            //Freq range to be searched
int Sign;                //Sign of last 3582A display binn
int Startbin;            //Binn # of first zero crossing
int stat;                //Status of instrument
double T;                      //Number of seconds in time record
int frange; //currently tested range
char tbuf[30];

   printf("getbeatnote... ");
   Newfreq=0;
   Order[1]=1;
   Order[2]=2;
   Order[3]=3;

   if ((Approxfreq<=85000) && (Approxfreq>100)) { Order[1]=2; Order[2]=1; Order[3]=3; }
   if (Approxfreq<=100) { Order[1]=3; Order[2]=2; Order[3]=1; }

    frange=1;
    do
    {
      Rangenum=Order[frange];

     if (Rangenum<3)
     {

      w3585("CN0 FA0HZ PR S2");
      if (Rangenum==1) { w3585("FB40MZ RB10KZ S2");}
      if (Rangenum==2) { w3585("FB85KZ RB300HZ S2");}

      do {
      w3585("D6T4");
      r3585(2);
      stat=Buffer[0];
      } while ((stat&0x80)==0x80); //wait until sweep complete

      w3585("C5CLSABOTB0");
      rd3585();
      Binn=2;
      Maxx=Display3585[2];
      for (I=3;I<=1000;I++)
      {
        if (Display3585[I]>=Maxx)
        {
          Binn=I;
          Maxx=Display3585[I];
        }
        //printf("%2u:%2X ",I,Display3585[I]&0xffff);
      }
      //printf("Maxx %u\n",Maxx);
      if (Maxx>=900) //sufficiently large signal found
      {

          sprintf(tbuf,"MK%dCN1 S3 RBUP D2 T6",Binn);
          //printf("%s\n",tbuf);
          w3585(tbuf);

          //printf("Read Frq...");
          wait_s01(5);
          r3585(12);
          Buffer[12]=0x00;
//          printf(">%s<\n",Buffer);

          Freq=atof(Buffer);

          w3585("TA0");
          if ((Binn>2)&&(Freq>=100.0)) {Newfreq=Freq;}
          //printf("%d\n",Binn);
          //printf("%f\n",Freq);
          //printf("New: %f\n",Newfreq);
      }

     } //end ranges 1 and 2 = 3585a ranges; need to implement 3562a ranges

     frange++;
    } while ((frange<=3) && (Newfreq<2));

    printf("beat frequency found [Hz]: %8.1f\n",Newfreq);

}




void Phi(int I,int Numelem,double *X,double *X1)
{
    int K;

//printf("call phi %d %d\n",I,Numelem);
    switch (I)
    {
    case 1: for (K=1;K<=Numelem;K++) {
        X1[K]=(1);
       }
     break;
    case 2: for (K=1;K<=Numelem;K++) {
        X1[K]=(X[K]);
       }
     break;
    case 3: for (K=1;K<=Numelem;K++) {
        X1[K]=(X[K]*X[K]);
       }
     break;
    case 4: for (K=1;K<=Numelem;K++) {
        X1[K]=(X[K]*X[K]*X[K]);
       }
     break;
    case 5: for (K=1;K<=Numelem;K++) {
        X1[K]=(1/X[K]);
       }
     break;
    }

}


double FNDot(int Numelem,double *E,double *F)
{
   int I;
   double Total;
//printf("call FNDot\n");
   Total=0;

   for (I=1;I<=Numelem;I++)
   {
      Total=Total+E[I]*F[I];
   }
   return Total;
}




void curvefit(double *X,double *Y,int Numelem,int N,double *C1,double *C2,double *C3,double *C4,double *C5) //Numelem: number of x, y elements; N number of coefficients
{
     int I,J,K;
     double C[5];
     double Element;
     double X1[100],X2[100],Temp[5][10],V[5],B[5][5];


//    ! Compute normal equations

//printf("Fit1\n");
     for (I=1;I<=N;I++)
     {
        Phi(I,Numelem,X,X1);
        for (J=1;J<=N;J++)
        {
           Phi(J,Numelem,X,X2);
           B[I][J]=FNDot(Numelem,X1,X2);
           B[J][I]=B[I][J];
        }
        V[I]=FNDot(Numelem,X1,Y);
     }
//    !MAT INVERSE GAUSS JORDAN REDUCTION
//printf("Fit2\n");
     for (I=1;I<=N;I++)
     {
        for (J=1;J<=N;J++)
        {
           Temp[I][J]=B[I][J];
           Temp[I][N+J]=0; //!INIT IDENTITY
         }
        Temp[I][I+N]=1;
     }
//    !DO DIAG
//printf("Fit3\n");
     for (I=1;I<=N;I++)
     {
        Element=Temp[I][I];

        for (K=1;K<=2*N;K++)
        {
           Temp[I][K]=Temp[I][K]/Element;
        }
//    !SET ELEMENTS OF COL=0
        for (K=1;K<=N;K++)
        {
           if ((K-I)!=0)
           {
             Element=Temp[K][I];
             for (J=1;J<=2*N;J++)
             {
                Temp[K][J]=Temp[K][J]-(Element*Temp[I][J]);
             }

           }
        }
     }
//printf("Fit4\n");
     for(I=1;I<=N;I++)
     {
        for (J=1;J<=N;J++)
        {
            B[I][J]=Temp[I][J+N];
        }
     }
//printf("Fit5\n");
//  !INVERSE FINISHED
     for (I=1;I<=N;I++)
     {
        C[I]=0;
        for (J=1; J<=N; J++)
        {
          C[I]=C[I]+B[I][J]*V[J];
        }
     }
//printf("Fit6\n");
     *C1=C[1];
     *C2=C[2];
     *C3=C[3];
     *C4=C[4];

     if (N==4)  { *C5=0; } else { *C5=C[5]; }

}




double Vrangemax; //             !Maximum allowable voltage tuning range
double Vrangemin; //              !Minimum allowable voltage tuning range

double Vrange;  //                 !voltage tuning range
double Vnom;   //   nominal tuning voltage

double Atten1; //                !Setting of attenuator 1
double Atten2; //                !Setting of attenuator 2
double Atten1db; //                !Setting of attenuator 1
double Atten2db; //                !Setting of attenuator 2


double Gain1;  //                !Setting of Gain1 (dB)
double Gain2; //                 !Setting of Gain2 (dB)

double Mixerfreq; //input frequency
double Userfrange; //frequency tuning range of user osc

double Vcoslope;
double Rin;

double Fbeatnote,Vbeatnote; //this is the setting used for the phase slope determination
//values are set by getvcoslope function

double Vnom_new; //suggested Vnom if zero beat too far off initial Vnom;
double Lockvoltage; //lock voltage

void getvcoslope(void)
{
    double B1,B2,B3,B4,B5;     //    !Coeffecients from least-squares fit
    double C1,C2,C3,C4,C5;    //     !Coeffecients from least-squares fit
    double Currentfreq;      //      !Present value of beatnote freq
    double Deltaf;          //       !Maximum freq change between beatnotes
    double Deltav;         //        !Control voltage step size
    double F0;             //        !Freq intercept (Freq at 0 volts)
    double Favg;          //         !Average of 4 freqs
    double F1linear;     //          !Linear approximation of Frequency(1)
    double F4linear;    //           !Linear approximation of Frequency(4)
    double Freq;       //            !Freq of user's oscillator
    double Maxfbeatnote; // max beatnote freq
    char tbuf[20];
    int Rangenum;
    int Trialcount;

    double Voltage[10],Voltagea[10],Voltagen[10];
    double Frequency[10],Frequencyn[10],Frequency2[10];

    double V,Vlower,Vupper,dacv,Vavg;

    double Lin, Lin2, Linslope;
    double Total;

    int i,j;

    int Maxindex;

    Vnom_new=Vnom;

    Deltav=Vrange*0.30;
    if ((Mixerfreq>=9.5E+7) && (Userfrange>5.0E+7)) { Deltav=Deltav*(5.0E+7/Userfrange);}
    if ((Mixerfreq<9.5E+7) && (Userfrange>=2.E+6)) { Deltav=Deltav*(2.E+6/Userfrange);}

    Deltav=0.045*Atten1*(Deltav / (0.045*Atten1));

    Deltav=FNMax(0.045*Atten1,Deltav);

    Deltaf=100000;
    Maxfbeatnote=200000;
    if (Mixerfreq>=9.5E+7) { Maxfbeatnote=4.E+6;}

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }

    Rangenum=(int)((rangedbv+13+4)/5+6);   //! +4 IS FOR ROUNDING
    sprintf(tbuf,"SV4R%02d",Rangenum);
    w3585(tbuf);

    toggle_i(OVERLOAD);

    Vcoslope=0.0;
    Trialcount=0;
    Freq=4.0E+7;

//     ! Step thru 4 voltages and get frequencies
     Vlower=Vnom-1.5*0.045*Atten1*((Deltav+0.5*0.045*Atten1)/(0.045*Atten1));
     Vupper=Vnom+1.5*Deltav;
    // printf("lower: %0.3f upper: %0.3f step: %0.3f \n",Vlower, Vupper, Deltav);
    for(V=Vlower;V<=Vupper;V=V+Deltav)
    {

        if (Vcoslope==0.0)
        {
          //  printf("Set dac: %0.3f\n",V/Atten1);
            value_i(DAC,V/Atten1);
       }

        if (Vcoslope==0.0)
       {
            Approxfreq=Freq+Deltaf;
            getbeatnote();
            Freq=Newfreq;
        }

        if (Vcoslope!=0.0)
        {
           Freq=fabs(Vcoslope*(V-Vnom));
        }

        //IF Abortflag=1 THEN Abortvcoslope

        if (Freq!=0)
        {
          Trialcount++;

          if (Trialcount==2) {Deltaf=Freq+Frequency[1];}

          Voltage[Trialcount]=V;
          Frequency[Trialcount]=Freq;

          dacv=valued[DAC]*0.045*Atten1;
          if (valued[DACNEG]==1) {dacv=-dacv; }
          Voltagea[Trialcount]=dacv; //actual DAC output voltage

          printf("Trial %d: Voltage: %0.3f actual Voltage: %0.3f Frq: %0.1f\n",Trialcount,V,dacv,Freq);
        }
     }//end of for loop

     if (Trialcount==4)
     {
        printf("Calculating VCO slope... ");

        Vavg=0;
        for (i=1;i<=4;i++)
        {
            Vavg+=Voltagea[i];
        }
        Vavg=Vavg/4; //average voltage
        for (i=1;i<=4;i++)
        {
            Voltagen[i]=Voltagea[i]-Vavg;
        }
        Favg=0;
        for (i=1;i<=4;i++)
        {
            Favg+=Frequency[i];
        }
        Favg=Favg/4; //average frequency

        for (i=1;i<=4;i++)
        {
            Frequencyn[i]=Frequency[i]-Favg;
        }

  //      printf("%0.3f avg v; %0.3f avg f\n",Vavg,Favg);

        Lin=99999;

        for (i=1;i<=4;i++)
        {
            Frequency2[i]=Frequency[i];
        //     printf("Frq #%d: %0.3f n=%0.3f\n",i,Frequency[i],Frequencyn[i]);
        }

        for (i=0;i<4;i++) //reverse sign starting from lowest frequency, check for lowest lin dev
        {
            if (i!=0)
            {
                Frequency[i]=-Frequency[i]; //succesively reverse sign
            }
            Linslope=(Frequency[2]-Frequency[3])/(Voltagen[2]-Voltagen[3]);
            if (Linslope!=0.0)
            {
              F0=Frequency[2]-Linslope*Voltagen[2];//  ! Get y-intercept  (b=y-mx)
              F1linear=Linslope*Voltagen[1]+F0;      //! Get predicted value for f1
              F4linear=Linslope*Voltagen[4]+F0;      //! Get predicted value for f4
              Favg=(Frequency[2]+Frequency[3])/2;

              if (!((Favg==F1linear) | (Favg==F4linear) | (Favg==Frequency[1]) | (Favg==Frequency[4])))
              {
                 Lin2=fabs(log10(fabs((Frequency[1]-Favg)/(F1linear-Favg))));
                 Lin2=Lin2+fabs(log10(fabs((Frequency[4]-Favg)/(F4linear-Favg))));
                 //printf("%0.3f\n",Lin2);
                 if (Lin2<=Lin)
                 {
                   Lin=Lin2;
                   for (j=1;j<=4;j++)
                   {
                      Frequency2[j]=Frequency[j];
                   }

                 }

              }

            }
        }


     for (i=1;i<=4;i++)
     {
   //     printf("#%d:  DAC Voltage: %8.3f    Frequency: %12.3f\n",i,Voltagea[i],Frequency2[i]);
     }

     printf("Fitting...\n");

     curvefit(Voltagen,Frequency2,4,4,&C1,&C2,&C3,&C4,&C5);

     for (i=1;i<=4;i++)
     {
        Frequency[i]=Frequency2[i];
     }

     //Mat1(Voltagen(*),"+",Vavg,1,4)     ! Restore original voltages
     //Voltagea has actual DAC voltages
     //Voltagen has voltagea - avg voltage

     if (Lin>.30)
     {
          printf("ERROR: Tuning curve is not linear! Lin parameter (0.3 max): %0.3f\n",Lin);
     }

//    ! Calculate Vcoslope at the tuning curve center voltage (Vnom)
     Vcoslope=(C2+2*C3*(Vnom-Vavg)+3*C4*(Vnom-Vavg)*(Vnom-Vavg))*Atten1;

     printf("VCO slope of current system (Hz vs. DAC Voltage): %0.4f Hz/V\n",Vcoslope);

//    ! Check to see if the total frequency tuning range is < .2 Hz
     if (Vrange*2*fabs(Vcoslope)/Atten1<0.2)
     {
          printf("ERROR: Tuning range less than 0.2 Hz!\n");
     }

     Rin=600.0; //VCO input impedance; 35601A has 50 ohm output impendace.


     printf("Expected VCO slope (Hz vs. VCO input voltage, 600 Ohm): %0.4f Hz/V\n",Vcoslope*((Rin+50)/Rin)/Atten1);


     Total=0; // calculate avg freq
     for (i=1;i<=4;i++)
     {
         Total=Total+Frequency[i];
     }
     Favg=Total/4;

     for (i=1;i<=4;i++)
     {
          Frequencyn[i]=Frequency[i]-Favg;
     }

     printf("Calculate lock point...\n");
     for (i=1;i<=4;i++)
     {
    //    printf("#%d:  DAC Voltage: %8.3f   avg. Frequency: %12.3f\n",i,Voltagea[i],Frequencyn[i]);
     }


     curvefit(Frequencyn,Voltagea,4,4,&B1,&B2,&B3,&B4,&B5);

//    ! Calculate the predicted Lock voltage and retune if it is
//    ! not within 15% of the total tuning range (Vnom +-.15*Vrange)

    // printf("Vavg: %f\n",Vavg);
    // printf("Favg: %f\n",Favg);

     Lockvoltage=B1+B2*(-Favg)+B3*(-Favg)*(-Favg)+B4*(-Favg)*(-Favg)*(-Favg);

     if ((Lockvoltage>(Vnom+0.15*Vrange)) | (Lockvoltage<(Vnom-.15*Vrange)) )
     {
         printf("!! Warning: predicted lock voltage is not within 15%% of the total\\n");
         printf("            tuning range, Vnom+-0.15*Vrange!\n");

         Vnom_new=0.045*Atten1*((Lockvoltage+0.0225*Atten1*fsgn(Lockvoltage)) / (0.045*Atten1));

         printf("!! Suggested Vnom = %0.3f Volt\n\n",Vnom_new);
     }
     //Lockvoltage=0.1;

//    ! Calculate the Vcoslope at the predicted lock point
     Vcoslope=fabs((C2+2*C3*(Lockvoltage-Vavg)+3*C4*(Lockvoltage-Vavg)*(Lockvoltage-Vavg))*Atten1);

     printf("Lock point, %e DAC Volt, VCO SLOPE = %e Hz/Volt\n",DROUND(Lockvoltage,3),DROUND(Vcoslope/Atten1,4));


//    ! Find the maximum vco frequency < Maxfbeatnote (Fbeatnote) and it's
//    ! DAC voltage (Vbeatnote). This will be used to measure Phase Slope.
     Maxindex=1;

     if (fabs(Frequency[4])>fabs(Frequency[1])) {Maxindex=4;}

     Fbeatnote=Frequency[Maxindex];

     if (fabs(Fbeatnote)>Maxfbeatnote) {Fbeatnote=Maxfbeatnote*fsgn(Fbeatnote);}

     Vbeatnote=0.045*((B1+B2*(Fbeatnote-Favg)+B3*(Fbeatnote-Favg)*(Fbeatnote-Favg)+B4*(Fbeatnote-Favg)*(Fbeatnote-Favg)*(Fbeatnote-Favg)) / 0.045);
     Fbeatnote=fabs(FNPround(C1+C2*(Vbeatnote-Vavg)+C3*(Vbeatnote-Vavg)*(Vbeatnote-Vavg)+C4*(Vbeatnote-Vavg)*(Vbeatnote-Vavg)*(Vbeatnote-Vavg),-3));

     printf("Beat note at %e DAC Volt, Freq = %e Hz\n",DROUND(Vbeatnote,3),DROUND(Fbeatnote,4));


     }
     else
     {
         printf("VCO slope could not be determined. Check setup/select other voltage range.\n");
     }
}





int Mixer;
double Mindac;
double Stfq,Spfq;
double Vswing;
int Numsam;
double Maxfreq;

void getuserparms(void)//this checks parameters and set up oscillator related variables
{

   Vrange=1.8;//+- voltage range
   Vnom=0.1;//center voltage of tuning curve

   Mixer=1; //1: 5 MHz to 1.6 GHz; 2: 1.2 to 18 GHz; 3: External 0.02 to 40.1 MHz
   Mixerfreq=28.8e6;//phase detector frequency

   Userfrange=1.0e6; //user total freq tuning range

   if (Mixerfreq>=9.5E+7)  {Maxfreq=4.0E+7;}
   if (Mixerfreq<9.5E+7) {Maxfreq=1.E+6;}


   if ((Vnom>10.0)|(Vnom<-10.0))
   {
       PError("Vnom out of range, use -10 to 10 Volts");
   }

   Vrangemax=12-fabs(Vnom);
   if (fabs(Vnom)<=2) {Vrangemax=10.035;}
   Vrangemin=0.18;
   if (fabs(Vnom)>0.765) {Vrangemin=0.36;}
   if (fabs(Vnom)>1.395) {Vrangemin=0.99;}
   if (fabs(Vnom)>3.96) {Vrangemin=1.98;}
   Vrange=fabs(Vrange);

   if ((Vrange<Vrangemin)|(Vrange>Vrangemax))
   {
       PError("Tuning range error!");
   }

   if ((Vrange+fabs(Vnom))>12)
   {
       PError("Center voltage+tuning range must be in -12 to 12 Volt range!");
   }

   Vswing=fabs(Vrange)+fabs(Vnom);
   Atten1=0.1;
   Atten1db=20;
   if (Vswing>1.2) {Atten1=0.2;Atten1db=14;}
   if (Vswing>2.4) {Atten1=0.5;Atten1db=6;}
   if (Vswing>6) {Atten1=1.0;Atten1db=0;}
   Mindac=0.045*Atten1;

   Vnom=Mindac*(floor(FNPround(Vnom/Mindac,-10)));
   Vrange=Mindac*(floor(FNPround(Vrange/Mindac,-10)));
   Vswing=fabs(Vrange)+fabs(Vnom);

   Atten1=0.1;
   Atten1db=20;
   if (Vswing>1.2) {Atten1=0.2;Atten1db=14;}
   if (Vswing>2.4) {Atten1=0.5;Atten1db=6;}
   if (Vswing>6) {Atten1=1.0;Atten1db=0;}
   Mindac=0.045*Atten1;


   Vnom=Mindac*(floor(FNPround(Vnom/Mindac,-10)));
   Vrange=Mindac*(floor(FNPround(Vrange/Mindac,-10)));

   printf("Center voltage of tuning curve: %0.3f Volt\n",Vnom);
   printf("Voltage tuning range: +- %0.3f Volt\n",Vrange);


   Atten2=1;
   Atten2db=0;
   if (Vrange<=(5*Atten1)) {Atten2=0.5; Atten2db=6.0;}

   if (Userfrange>1.0e6)
   {
       printf("Total frequency tuning range (user defined): %0.3f\n",Userfrange);
   }

   if (Userfrange<=1.0e6)
   {
       printf("Total frequency tuning range (user defined): less than or equal 1 MHz!\n");
   }

   switch (Mixer)
   {
       case 1: printf("Internal 5 MHz to 1.6 GHz mixer used.\n");
          if ((Mixerfreq<4.9e6)|(Mixerfreq>1600e6))
          {
              PError("Frequency must be in 4.9 MHz to 1600 MHz range. Check frequency or select other mixer!");
          }
       break;
       case 2: printf("Internal 1.2 to 18 GHz mixer used.\n");
          if ((Mixerfreq<1200e6)|(Mixerfreq>18000e6))
          {
              PError("Frequency must be in 4.9 MHz to 1600 MHz range. Check frequency or select other mixer!");
          }
       break;
       case 3: printf("External mixer. Connect mixer IF port to 35601A SIGNAL INPUT port.\n");

       break;
       default: PError("No mixer selected!");
       break;
   }
   printf("Phase detector input frequency: %0.1f Hz\n",Mixerfreq);

   Stfq=25000;//start freq
   Spfq=1e6;//stop freq
   Stfq=DROUND(Stfq,5);
   Spfq=DROUND(Spfq,5);

   if (Spfq<=Stfq) {printf("!!Error: Stop frequeny must be greater than start frequency!\n");}

   Numsam=1;//number of averages

   if ((Numsam<1)|(Numsam>999)) {printf("!!Error: Number of sample must be in range of 1 to 999!\n");}

}

//this version modified for 3562a fft analyzer!
void Getfreqparms(double Beginfreq,double Endfreq, int *Beginindex,int *Endindex)
{
   if (Endfreq<=4) {*Endindex=3;} //lowest index for 3562a
   if (Endfreq>4) {*Endindex=4;}
   if (Endfreq>10) {*Endindex=5;}
   if (Endfreq>40) {*Endindex=6;}
   if (Endfreq>100) {*Endindex=7;}
   if (Endfreq>400) {*Endindex=8;}
   if (Endfreq>1000) {*Endindex=9;}
   if (Endfreq>4000) {*Endindex=10;}

   if (Endfreq>25000) {*Endindex=11;} //3585a indices
   if (Endfreq>500000) {*Endindex=12;}
   if (Endfreq>5e6) {*Endindex=13;}

   if (Beginfreq<4) {*Beginindex=3;} //index 3 is lowest index for 3562a
   if (Beginfreq>=4) {*Beginindex=4;}
   if (Beginfreq>=10) {*Beginindex=5;}
   if (Beginfreq>=40) {*Beginindex=6;}
   if (Beginfreq>=100) {*Beginindex=7;}
   if (Beginfreq>=400) {*Beginindex=8;}
   if (Beginfreq>=1000) {*Beginindex=9;}
   if (Beginfreq>=4000) {*Beginindex=10;}

   if (Beginfreq>=25000) {*Beginindex=11;} //3585a indices
   if (Beginfreq>=500000) {*Beginindex=12;}
   if (Beginfreq>=5e6) {*Beginindex=12;}
}


//3562a has 801 bins!
int P[14][3]={{0,0,0}, //entry seg 0   data are startbin stopbin and fmax
                 {0,0,0},   //entry seg 1
                 {0,0,0},   //entry seg 2
                 {4,800,4},  //seg 3 is lowest used for 3562a
                 {320,800,10}, //4
                 {200,800,40}, //5
                 {320,800,100}, //6
                 {200,800,400}, //7
                 {320,800,1000}, //8
                 {200,800,4000}, //9
                 {128,800,25000},   //10
                 {50,1000,50},   // 11 (SEGS 11-13 HAVE FMAX/10000)
                 {100,1000,500},    // 12
                 {125,1000,4000}   // 13
                };
//these are indices -2, -1, 0 to initialize P85 and P82
//new indices are 1008 1009 1010


int Amplifier=1; //K11 amplifier in or out
int AutoK11=1; //K11 amplifier out if overload
int Oldfilter=-1;
int Startindex,Stopindex;

void getdata(void) //perform actual data taking for a phase noise measurement
{
    int Rangenum;
    int Reflevel85;
    int Start85;
    int Stop85;
    int Index85;
    char tbuf[100];
    int SRQstate;
    char SerialPollResponse ;
    int Spectrum[1050];
    int I;

    for(I=11;I<=13;I++)
    {
        P85[I][1007]=0;//this is the data valid flag
        P85[I][1008]=P[I][0];
        P85[I][1009]=P[I][1];
        P85[I][1010]=P[I][2];
    }
    for(I=1;I<=10;I++)
    {
        P82[I][1007]=0;//this is the data valid flag
        P82[I][1008]=P[I][0];
        P82[I][1009]=P[I][1];
        P82[I][1010]=P[I][2];
    }


    if (Maxfreq<=1e6) {P85[12][1009]=200;} //limit 3585a to 2 MHz if 2 MHz filter is in.


  //**  if (Amplifier==1) {setup_i("K11");} else {setup_i("-K11");}
  //**  setup_i("K10,K12,S8,L1,L2,L3"); //set up for measurement

    wait_s01(20);

    toggle_i(OUTOFLOCK);


    autorange85();


    if (rangedbv>=-3)
    {
        printf("!!Warning: High noise power! Consider removing amplifer to avoid compression!\n");

       if (AutoK11==1)
       {
          setup_i("-K11,S8");
          printf("Note AutoK11: K11 amp has been removed to avoid compression!\n");
          Amplifier=0;
          autorange85();
       }
    }

    Rangenum=(rangedbv+13)/5+6;
    Reflevel85=rangedbv;
    Rangenum=FNMax(1,Rangenum-2);  // ! Down range by 10 dB

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }

    wait_s01(3);
    sprintf(tbuf,"AL0SV4R12RL%dDVR%02d",Reflevel85,Rangenum);
    w3585(tbuf); //setup 3585a

    //**missing: check if locked

    Getfreqparms(Stfq,Spfq,&Startindex,&Stopindex);

       //Sweepflag=0;


//    ! Get start and stop indexes for 3582A and 3585A

//    Start82=0
    Start85=0;
 //   Stop82=0
    Stop85=0;
 //   IF Startindex<=10 THEN Start82=Startindex
 // IF Startindex<=10 THEN Stop82=FNMin(10,(Stopindex))

     if (Startindex<11) {printf("!!Error: Freq index too low; not yet supported! Start index set to 11!\n");}
     if (Stopindex>=11) {Start85=FNMax(11,(Startindex));}
     if (Stopindex>=11) {Stop85=Stopindex;}

     Index85=Stop85;

//    ! Set up 3585A to take measurement
     w3585("PRRLDVAR0FA0HZMK1001S2D2");


     if (Index85==13) {w3585("C1 FB40MZ RB30KZ VB100HZ ST20SC RC4SV4");}
     if (Index85==12) {w3585("C1 FB5MZ RB10KZ VB30HZ ST20SC RC4SV4");}
     if (Index85==11) {w3585("C1 FB500KZ RB1KZ VB10HZ ST50SC RC4SV4");}
     w3585("T5");

//3517 Segment85loop:    ! loop here until sweep done (SRQ)
//3520  Phioff(P85(*),Index85,Vcoindex,Measuretype,Amplifier,Mixerfreq,Caldata(*),W1,W2,W3,Loopbw1,Phaseslope,Vcoslope,Vcofreq)
//3529 Seg85waitloop:   !


//    sprintf(tbuf,"SV4R%02d",Rangenum);
//    w3585(tbuf);

    printf("3585A start index: %d\n",Start85);
    printf("3585A stop index: %d\n",Stop85);
do {//index85 loop
     printf("waiting for 3585A data at index %d...\n",Index85);
     do {
      TestSRQ(BoardIndex,&SRQstate);
      //printf("%d",SRQstate&0x01);
      wait_s01(5);
    }
    while (!(SRQstate&0x01));

    TestSRQ(BoardIndex,&SRQstate);
   //printf("%d",SRQstate&0x01);
   //printf ( "Device asserted SRQ.1\n" );
    ibrsp ( Device3585, &SerialPollResponse);
    //TestSRQ(BoardIndex,&SRQstate);
    //printf("%d",SRQstate&0x01);
    //printf ( "SRQ cleared.2\n" );

    w3585("C5 CL SA TB0 BO");

    rd3585();//read data into Display3585 variable

    for (I=0;I<=1000;I++)
    {
        Spectrum[I]=(Display3585[I+1]);//first point is always 0xffff
        //if (I<15) {printf("%d: %u\n",I,Spectrum[I]);}
    }
    Spectrum[1000]=Spectrum[1000]&(int)1023;
    for (I=0;I<=1005;I++)
    {
        Spectrum[I]=10*(Reflevel85-100)+Spectrum[I];
        //if (I<5) {printf("%d: %d\n",I,Spectrum[I]);}
    }

//    !  SPECTRUM now contains raw spectrum data *10

    for (I=0;I<=1000;I++)
    {
        P85[Index85][I]=Spectrum[I];
  //      tracedata[Index85][I]=((double)Spectrum[I])/10.0;
    }
    P85[Index85][1007]=1; //valid trace
//    tracedata[Index85][1007]=1.0; //valid trace

     Index85=Index85-1;

 //**missing: check if still locked

     if (Index85==13) {w3585("C1 FB40MZ RB30KZ VB100HZ ST20SC RC4SV4");}
     if (Index85==12) {w3585("C1 FB5MZ RB10KZ VB30HZ ST20SC RC4SV4");}
     if (Index85==11) {w3585("C1 FB500KZ RB1KZ VB10HZ ST50SC RC4SV4");}

     w3585("D2T5"); //start next sweep

    } while (Index85>=Start85);

}

/*
11884   ! * NAME: Phaseslope
11887   ! *
11890   ! * FUNCTION: Measure the phase slope of the beatnote from the mixer.
11893   ! *
11896   ! * INPUT: Voltage, Atten1, Freq, Mixerfreq, Caldata(*), Rangedbv, Amplifier
11899   ! * OUTPUT: Phaseslope, Vpeak
! If Measuretype=0 then this routine is used to measure Phase Slope.
11986   ! The formula used to calculate phase slope is:
11989   !
11992   !  2^.5 * (V0 - 3*V1 + 5*V2 - 7*V3 + 9*V4 ...)
11995   !  V0-Vx are rms values of each harmonic component
11998   !
12001   ! Cutoffamp designates minimum levels that each
12004   ! harmonic must be greater than to be of significance.
12007   !
12010   ! Phaseslope can be in error if there is a significant amount of
12013   ! dc offset from the mixer.  This is taken into account by the
12016   ! term COS( ASN( Mixerdc/V0 )).
12019   !
12022   ! If Measuretype#0 then this routine is used to measure the amplitude of the
12025   ! input signal. No harmonics are needed so Fmax is set to
12028   ! twice the expected frequency.
*/

double Cutoffamp[19]={0.0,-100.0,0.0,
                      -49.5,0.0,-54.0,
                      0.0,-57.0,0.0,
                      -59.0,0.0,-61.0,
                      0.0,-62.3,0.0,
                      -63.5,0.0,-64.7,0.0};
                        //      !Amplitude rel to peak where harmonic becomes insignificant

double Phaseslope;
double Mixerdc;
double Vpeak;

void Getphaseslope(double Voltage,double Freq, int Measuretype,int Caltype)
{
    int Binc;             //   !For-next loop counter
    int Binn;              //  !Approximate display bin of response

    double Famp;             //      !Amplitude of particular freq
    double Famp1;           //       !Amplitude of fundamental
    double Fb;              //       !Maxfreq on 3585A span
    double Fmax;             //      !Max freq needed to measure phaseslope
    double Fullscale;        //      !Reflevel of 3582A
    int Harmonic;           // !Harmonic number being checked
    double Hzpbin;          //       !Hz per display bin
    int Maxbin;             // !Bin # of max response
    int Maxx;               // !Value of max response
    double Mixerdc1;        //       !Total dc in path
    double Mixerdc2;         //      !Residual dc in path
    int Numharmonics;       // !Number of harmonics to be checked
    int Rangenum;           // !Range number of 3585A
    int Sens;               // !Sensitivity setting of 3582A
    double Sign;               // !Sign of current harmonic value to be added
    int Span;               // !Span number of 3582A
    int Stat;               // !Result of STATUS read of instrument
    char tbuf[100];
    int I;
    int Display[1050];
    int Minbinnt;
    double FNCp;

    printf("measuring phase slope...\n");


    Mixerdc=0;

    if (Measuretype==0)  { value_i(DAC,Voltage/Atten1);} //set beat note
    toggle_i(OVERLOAD);
    Fmax=Freq*10.0;
    if ((Measuretype==2) | (Measuretype==1) & (Caltype!=2))
    {
        Fmax=Freq*2.0;  // ! DISCRIMINATOR OR QUADRATURE CAL
    }

    if (Freq>=2500) //3585a used if >=2.5 khz
    {

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }
    wait_s01(3);

    Rangenum=(int)((rangedbv+13+4)/5+5);//  !+4 IS FOR ROUNDING
    Rangenum=FNMax(1,Rangenum);
    Rangenum=FNMin(12,Rangenum);
    Fb=1000.0*(Fmax / 1000.0+1.0); //     // !calculate max freq needed
    Fb=FNMin(4.01E+7,Fb);

    sprintf(tbuf,"R%02dFB%8.1fHZ PR RL UP UP RC4 SV4 S2S2",Rangenum,Fb);
    w3585(tbuf); //setup 3585a

     do {
      w3585("D6T4");
      r3585(2);
      stat=Buffer[0];
      } while ((stat&0x80)==0x80); //wait until sweep complete

      w3585("C5CLSA BO TB0");
      rd3585();

      for (I=0;I<=1001;I++)
      {
        Display[I]=Display3585[I];
      }

      Display[0]=Display[0]&1023;
      Display[1000]=Display[1000]&1023;

      Maxbin=0;//to avoid compiler warning
      Maxx=-200;
      Hzpbin=Fb/1000;
      Minbinnt=(int)(Freq/5.0/Hzpbin); //temporary variable for type conversion

      for (Binn=Minbinnt;Binn<=1000;Binn++)
      {
         if(Display[Binn]>Maxx) {Maxbin=Binn;}
         Maxx=FNMax(Display[Binn],Maxx);
      }

      Hzpbin=Fb/1000;
      Freq=Maxbin*Hzpbin;

      w3585("RLDVD7T4");
      r3585(100);
      //printf("\n%s\n",Buffer);
      for (I=3;I<10;I++) //extract ref level info
      {
          tbuf[I-3]=Buffer[I];
      }
      tbuf[6]=0;
      //printf("\n>%s<\n",tbuf);
      Fullscale=atof(tbuf);
      //printf("%f\n",Fullscale);

      Sign=1.0;
      Phaseslope=0;
      Numharmonics=9;
      if ((Measuretype==2) | (Measuretype==1) & (Caltype!=2))
      {
        Numharmonics=1;  // !IF Measuretype#0, NOT A BEATNOTE; this is for carrier ampl measurement
      }

      for (Harmonic=1; Harmonic<=Numharmonics; Harmonic=Harmonic+2)
      {
        Binn=(int)(Freq*Harmonic/Hzpbin);
        Maxx=-1;

        for (Binc=FNMax(10,Binn-25);Binc<=FNMin(1000,Binn+25);Binc++)
        {
          Maxx=FNMax(Maxx,Display[Binc]);
        }

        Famp=(double)Fullscale-(1000.0-(double)Maxx)/10;

        printf("found harmonic no. %d: amplitude: %f\n",Harmonic,Famp);
        FNCp=FNCalpoint(Amplifier,0,Mixerfreq,0,0,0,0,0,0,Freq*Harmonic);
        Famp=Famp+FNCp;
        printf("%0.2f FNCalp, corrected amplitude: %0.2f\n",FNCp,Famp);


        if (Harmonic==1)  {Famp1=Famp;}



        if ((Famp-Famp1)>=Cutoffamp[Harmonic])
        {
          Phaseslope=Phaseslope+Sign*(double)Harmonic*pow(10,((double)Famp)/20);
          Sign=Sign*(-1.0);
        } else
        {
            printf("Harmonic no. %d below cut-off, %f!\n",Harmonic,Cutoffamp[Harmonic]);
            Harmonic=10000; //end loop
        }

      }

      if (Amplifier==1) {Phaseslope=Phaseslope/50;} // 40 db amp has 34 db=x50 amplification into 50 ohm because of series resistor!

      if ((Measuretype==2) & (Amplifier==1) & ((Caltype==2) | (Caltype==3))) {Famp1=Famp1-34;}
                    //with amp present, 40 db amp has 34 db gain into 50 ohm

      if (!((Measuretype==2) | (Measuretype==1) & (Caltype!=2)))
      {
/*
12541    OUTPUT I3582;"PRS HLT AA0 AB1 MD2 IM3 SC1 RP0 MN1 MP0 SP10 BS5 RUN"
12544    OUTPUT I3582;"AR"
12547    OUTPUT I3582;"AR"
12550    WAIT .7
12553    CALL Getdc(Mixerdc1)
12556    Setupinterface(" K2,-K12")
12559    OUTPUT I3582;"AR"
12562    WAIT .7
12565    Getdc(Mixerdc2)
12568    Setupinterface("-K2,K12")
12571    Mixerdc=Mixerdc1-Mixerdc2
*/
      }

      Phaseslope=Phaseslope*pow(2.0,0.5);

      Vpeak=pow(10,(Famp1/20))*pow(2.0,0.5); // !peak value of fundamental, convert RMS to peak

      if (Measuretype==0)
      {

      //  PRINT "MIXERDC=";FNPround(Mixerdc,-4);"Volts   VPEAK=";FNPround(Vpeak,-4);"Volts"

    printf("Measured mixer DC = %e (dummy) Volt; Vpeak = %e Volt\n",FNPround(Mixerdc,-4),FNPround(Vpeak,-4));


    if (fabs(Mixerdc/Vpeak)>0.5)
        {printf("!! Error REF  314;DC OFFSET FROM MIXER > 1/2 PEAK VOLTAGE\n");}

    Phaseslope=Phaseslope*cos(asin(Mixerdc/Vpeak)); //correct for (small) DC component

    printf("Measured phase slope = %e Volt/Radian\n",FNPround(Phaseslope,-3));

    if ((Phaseslope<0.0195)|(Vpeak<0.0195))
        {printf("!! Error REF 312: PHASE SLOPE LESS THAN 20.0 mV\n");}

    if (Phaseslope>10.0)
        {printf("!! Error REF 313; PHASE SLOPE GREATER THAN 10 V\n");}

     }


/*


     } else  //use lf analyzer
     {
*/
     }

}



void Lockcheck(int *Lockflag)
{

  //*** need to add!

  *Lockflag=1;
/*
10255   ! *
10258   ! *  NAME: Lockcheck
10261   ! *
10264   ! *  FUNCTION: Check to see if the PLL is locked.
10267   ! *
10270   ! *  INPUT:  Phaseslope
10273   ! *
10276   ! *  OUTPUT: Lockflag
10279   ! *
10282 Lockcheck:SUB Lockcheck(INTEGER Lockflag)
10285    COM /Loc_flags/ INTEGER C9835,I3582,I3585,I35601a,Clock,Plotter,Abortflag,Printer
10288    COM /Settings/ Latch(0:9)
10291    COM /Parm1/ REAL Cfq,Phaseslope,Vcoslope,I85amp,Loopbw1
10294    COM /Parm2/ REAL Vpeak,Vnom,Vrange,W1,W2,Mixerfreq,Errorspec,Mixerdc
10297    REAL Vswing
10300    REAL Gain
10303    REAL Gain1
10306    REAL Gain2
10309    REAL Dac         ! DAC VOLTAGE
10312    REAL Dc          ! Dc value from hf-board into 3582A
10315    REAL Atten1      ! Atten1 from hf_board
10318    REAL Atten2
10321    REAL Orgdac
10324    REAL Mixerdcg    !
10327    REAL I           ! For-next loop counter
10330    INTEGER Lockcount! Number of times lock has been checked
10333    INTEGER Loopcount! Loop counter
10336    INTEGER Maxx     ! Maximum of 3585A display
10339    INTEGER Rangenum ! Range setting for the 3585A
10342    ON KEY 19,5 GOTO Abortlockkey
10345    ALLOCATE Display(0:1001)
10348    ENABLE
10351    Lockflag=0
10354    Vswing=ABS(Vrange)+ABS(Vnom)
10357    Atten1=1/10
10360    IF Vswing>1.2 THEN Atten1=1/5
10363    IF Vswing>2.4 THEN Atten1=1/2
10366    IF Vswing>6 THEN Atten1=1
10369    Atten2=1
10372    IF Vrange<=5*Atten1 THEN Atten2=.5
10375    Gain=2*(20*LGT(Vrange/Atten1/Vpeak) DIV 2)
10378    IF Gain>54 THEN Gain=54
10381    Gain=Gain-12+6
10384    Gain=Gain+6*(Atten=.5)
10387    Gain2=20-Gain MOD 4
10390    IF Gain<18 THEN Gain2=Gain
10393    Gain2=FNMax(6,Gain2)
10396    Gain1=Gain-Gain2
10399    Mixerdcg=-1*(Atten2*Mixerdc*10^((Gain1+Gain2+6)/20))
10402    Dac=Vnom/Atten1
10405    Orgdac=Dac
10408   !
10411   ! CHECK FOR BEATNOTE IF NO BEATNOTE THEN CHECK FOR PLL
10414   !
10417    IF ABS(Mixerdcg)>.10*Phaseslope THEN Highbeat
10420    GOSUB Beatsearch
10423    IF Beatflag=0 THEN Checkflip!NO BEAT CHECK LOCK
10426   ! OPEN LOOP
10429    Setupinterface("-K10")
10432    WAIT 2.2
10435   ! CLOSE LOOP
10438    Setupinterface("K10")
10441    WAIT 1.2
10444    GOSUB Beatsearch
10447    IF Beatflag=1 THEN Lockcheckexit
10450 Checkflip: !
10453    Setupinterface("-L0,L9")
10456    DISP CHR$(130)&CHR$(127)&CHR$(128)&"CHECKING LOCK"
10459    OUTPUT I3582;"PRS,SC1,MN1,AC2,MP0"
10462    Loopcount=0
10465 Lockcheckloop:  !
10468    WAIT .5
10471    GOSUB Checklk    ! Check OUT OF LOCK FLIP on 3582A
10474    Loopcount=Loopcount+1
10477    IF (Loopcount<2) AND (Lockflag=0) THEN Lockcheckloop
10480    GOTO Lockcheckexit
10483 !
10486 ! POSSIBLE HIGHFREQ BEATNOTE NEED TO BRING IT IN
10489 !
10492 Highbeat:!
10495   ! FIND DAC STEP VOLTAGE
10498    IF (Dac-Mixerdcg<=0) AND (Dac>0) THEN Steps=-.2
10501    IF (Dac-Mixerdcg>0) AND (Dac>0) THEN Steps=-1
10504    IF Dac=0 THEN Steps=SGN(Mixerdcg)*.2*(-1)
10507    IF (Dac-Mixerdcg>=0) AND (Dac<0) THEN Steps=.2
10510    IF (Dac-Mixerdcg<0) AND (Dac<0) THEN Steps=1
10513    IF (SGN(Dac)<>SGN(Mixerdcg)) AND (SGN(Dac)<>0) THEN Steps=Steps*(-1)
10516    Finalv=Dac-Mixerdcg
10519    IF ABS(Finalv)>10.4 THEN Finalv=10.4*SGN(Finalv)
10522    GOSUB Movedac
10525    GOSUB Beatsearch
10528    Finalv=Orgdac
10531    Steps=Steps*(-1)
10534    IF Beatflag=0 THEN GOSUB Movedac
10537    IF Beatflag=0 THEN Checkflip
10540   !
10543   ! OPEN LOOP
10546   !
10549    Setupinterface("-K10")
10552    WAIT 2
10555    Setupinterface("K10")
10558    WAIT 1
10561    GOSUB Beatsearch
10564    GOSUB Movedac
10567    IF Beatflag=1 THEN Lockcheckexit
10570    GOTO Checkflip
10573 Abortlockkey: !
10576    DISP "MEASUREMENT ABORTED BY USER"
10579    BEEP
10582    WAIT 1
10585    Abortflag=1
10588    GOTO Lockcheckexit
10591 Abortlock1:   !
10594    DISP "REF 311; DAMAGING INPUT SIGNAL, MEASUREMENT ABORTED"
10597    Errorbeep
10600    WAIT 2
10603    Abortflag=1
10606    GOTO Lockcheckexit
10609 Lockcheckexit:!
10612    SUBEXIT
10615 !
10618 ! CHECK FOR PRESENCE OF BEATNOTE
10621 !
10624 Beatsearch:!
10627    CLEAR I3585
10630    Rangenum=(20*LGT(Phaseslope)+13)/5+6
10633    OUTPUT I3585 USING "K,ZZ,K";"R",Rangenum,"RC4 SV4 S2"
10636    Toggle("OUT OF LOCK")
10639    OUTPUT I3585;"S2"
10642 Sweepwait:OUTPUT I3585;"D6T4"
10645    ENTER I3585 USING "#,B";Stat
10648    IF BIT(Stat,7) THEN Sweepwait
10651    OUTPUT I3585;"C5CLSATB0BO"
10654    ENTER I3585 USING "#,W";Display(*)
10657    OUTPUT I3585;"S1"
10660    Display(0)=0
10663    Display(1)=0
10666    Display(1001)=0
10669    Total=0
10672    FOR I=0 TO 1001
10675       IF Display(I)>900 THEN
10678          Display(I)=1
10681       ELSE
10684          Display(I)=0
10687       END IF
10690       Total=Total+Display(I)
10693    NEXT I
10696    Beatflag=1
10699    IF Total=0 THEN Beatflag=0
10702    RETURN
10705 !
10708 ! MOVE DAC VOLTAGE
10711 !
10714 Movedac:!
10717    IF Mixerdcg=0 THEN RETURN
10720    FOR I=Dac TO Finalv-Steps STEP Steps
10723       Dac=Dac+Steps
10726       Setupbits("DAC",Dac)
10729    NEXT I
10732    Setupbits("DAC",Finalv)
10735    Dac=Finalv
10738    RETURN
10741   !
10744   !
10747   !
10750 Checklk:      !
10753    Lockflag=0
10756    Toggle("OUT OF LOCK")
10759    WAIT .5
10762    Getdc(Dc)
10765    IF Dc>2 THEN Abortlock1
10768    IF (Dc>=.9) AND (Dc<=2) THEN RETURN
10771    Lockflag=1     ! SET LOOP LOCKED FLAG
10774    RETURN   ! **FF****
10777 SUBEND
10780   ! *

*/
}



void Lagleadcalc(void)
{
    W2=2.0*M_PI*Zerofreq[(int)Laglead];
    W3=1.0/(R25*C8+1.0/W2);
    Loopbw3=Loopbw1*W3/W2;

//   ! Check to see if open loop bw is less than lag-lead pole freq W3
    if (Loopbw1<W3/(2.0*M_PI)) {Loopbw3=Loopbw1;}

//   ! Check to see if open loop bw is >= than pole-freq W3 and less than
//   ! lag-lead zero freq W2
    if ((Loopbw1>=W3/(2.0*M_PI)) & (Loopbw1<W2/(2*M_PI)))
        {Loopbw3=sqrt((Loopbw1*W3/(2.0*M_PI)));}

    printf("LAG LEAD=%0.1f\n",Laglead);
    printf("LOOP BANDWIDTH=%0.1f\n",Loopbw3);

    if (Laglead==0) {setup_i("-S4");} //search osc
    if (Laglead!=0) {setup_i("S4");}
    value_i(LEADLAG,Laglead);

    if (Loopbw3>20.0) {setup_i("-L0,L9,-S1,-S5,K7,K6,S2");} //connect tracking gen?
    if (Loopbw3<=20.0) {setup_i("L0,-L9,S1,S5,-K7,-K6,-S2");} //connect noise source?

    if ((Loopbw3>250000) & (Laglead!=7))
      {
          printf("!! Error: Loop bandwidth error REF 323; UNABLE TO ACHIEVE PHASE LOCK!\n");
      }
        else { printf("BW OK: LOOP BANDWIDTH=%0.2f Hz\n",FNPround(Loopbw3,-2));}

     Vcofreq=Loopbw3/4.0;
}

void waitfor3585(void)
{
   char stat;
      do {
      w3585("D6T4");
      r3585(2);
      stat=Buffer[0];
      } while ((stat&0x80)==0x80); //wait until sweep complete
}


void Charloop() //int Pdv,int Vcoindex
{

    int Binn; //               !Bin # of display
    int Bwincrease; //         !0=ok to increase bandwidth, 1=already increased
    double C1,C2,C3,C4,C5; //        !Curve fit coeffecients
 //   double C8; //                     !Capacitor in lag-lead
    double Corner; //                 !Freq of pole in lag-lead
    int Count; //               !Index counter
    double Fw; //                     !Value of transfer function at w
    double Gain; //                   !Amount of gain in programmable gains
  //  double Gain1; //                  !0->28 dB in 4 dB steps
  //  double Gain2; //                  !6->20 dB in 2 dB steps
    double Hzpbin; //                 !Hz per display bin
    double Hzpbin2; //                !Hz per bin used for plot of loop
    int I; //                   !For-next loop counter
    int J; //                   !For-next loop counter
    double Junk; //                   !Dummy variable for non-usable value read from the 3585A
    int Lockflag; //            !0=loop not locked, 1=loop locked
    double Loopbw2; //                !
    int Maxindex; //            !Index where max response occured
    double Maxpointerror; //          !Max error determined by Difcorrection
    double Maxx; //                   !Value of max response
    int N; //                   !Number of points for differential correction
    int Numsamples; //          !Number of samples on 3582A XFER function
    double Oldloopbw1; //             !Initial calculation of Loopbw1
  //  double R25; //                    !Resistor in lag-lead
    double Rc2pi; //                  !Product of 2*PI*R*C
    int Sens; //                !Sensitivity setting of the 3582A
    int Span; //                !Span number of the 3582A
    int Stat; //                !Status read from the 3582A or 3585A
    double Wi; //                     !Radian freq
    double X[101]; //               !Freq's to be used for curve fit
    double X1; //                     !Freq to be put in X(*)
    double Y[101]; //               !Amp's to be used for curve fit
    double Zero; //                   !Desired Leadfreq in lag-lead
    int forcellg2;
    int retrychar; //retry characterization at other laglead
    int Display[1050];
    char tbuf[100];

//   ! Zero freqs are calculated from the resistor selected by
//   ! the following formula:   f=1/(2*PI*(R+100)*C8)
//   ! 100 is the switch resistance

 //    C8=3.3E-8;               //  ! .033 uf
 //    R25=4.823E+5          //    ! 482K ohm


    printf("\nCharacterizing the loop...\n");

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }
    wait_s01(3);


//   ! DETERMINE GAIN SETTINGS
     Gain=2.0*(20.0*log10(Vrange/Atten1/Vpeak) / 2.0);

     if (Gain>54.0) {Gain=54.0;}
     Loopbw1=fabs(Phaseslope*Vcoslope*pow(10,Gain/20.0)); // ! OPEN LOOP BW
 printf("LOOP BW1 (uncorrected)=%e\n",Loopbw1);
     Loopbw1=Loopbw1/pow(10,(FNCalpoint(0,0,Mixerfreq,0,0,0,0,0,0,10000.0)/20.0));   //   ! ADJUST PHASESLOPE TO MEASUREMENT POINT
 printf("LOOP BW1 (FNCalp corrected)=%e\n",Loopbw1);
    Gain=Gain-12.0+6.0;          //  !TAKE OUT x4(12dB) AMPLIFIER AND 6dB PAD
    if (Atten2==0.5) {Gain=Gain+6;} //  !ADD 6 dB IF ATTEN2=.5
    Gain2=20.0-fmod(floor(Gain),4.0);     //  !CHOOSE 20 OR 18 dB FOR GAIN2
    if (Gain<18) {Gain2=Gain;}   //   !USE LESS IF GAIN<18
    Gain2=floor(Gain2/2.0)*2.0;
    Gain2=FNMax(6,Gain2);          //  !GAIN2 HAS 6 dB MIN
    Gain1=Gain-Gain2;         // !PUT REMAINING GAIN IN GAIN1
    Gain1=floor(Gain1/4.0)*4.0;

    Loopbw1_actual=fabs(Phaseslope*Vcoslope*pow(10,(Gain1+Gain2)/20.0)); // ! OPEN LOOP BW


    value_i(GAIN1,Gain1);
    value_i(GAIN2,Gain2);

    value_i(DAC,Vnom/Atten1);
  //  value_i(DAC,Lockvoltage); //only for unstable osciallators that are not within 15% range

    setup_i("L2,K10,S3"); //close loop
    wait_s01(20);
    toggle_i(OUTOFLOCK);

    printf("GAIN=%0.2f\n",Gain);
    printf("GAIN1=%0.2f\n",Gain1);
    printf("GAIN2=%0.2f\n",Gain2);
    printf("VCOSLOPE=%e Hz/V\n",Vcoslope/Atten1);
    printf("PHASESLOPE=%e V/rad\n",Phaseslope);
    printf("VPEAK=%0.2f V\n",Vpeak);
    printf("LOOP BW1=%e\n",Loopbw1);
    printf("LOOP BW1 (with actual gain)=%e\n",Loopbw1_actual);

    //Loopbw1=Loopbw1_actual;
    //printf("Note: using LOOP BW1 calcuated based on actual gain!\n");
    printf("Note: using LOOP BW1 calcuated based on %0.2f dB Gain!\n",Gain);

// ! Calculate BW assuming far out zero
    Corner=1.0/(2.0*M_PI*R25*C8);
    Loopbw2=sqrt(Loopbw1*Corner);  // ! Geometric mean, approximate cross-over

    printf("CORNER=%e\n",Corner);
    printf("LOOP BW2=%e\n",Loopbw2);

//   ! DETERMINE WHICH ZERO TO USE
    Zero=Loopbw2/sqrt(2.0);

    Laglead=0.0;

    for (I=11;I>=0;I--)
    {
       if (Zerofreq[I]<Zero) {Laglead=I;}
    }
    printf("INITIAL LAG LEAD CHOICE=%0.1f\n",Laglead);
    printf("NEEDED ZERO FREQ=%0.2e\n",Zero);
    printf("ACTUAL ZERO FREQ=%0.2e\n",Zerofreq[(int)Laglead]);

    Laglead2=Laglead;
    Bwincrease=0;

    forcellg2=0; //flag to force ext laglead2
    if (Laglead>7) {
            printf("!! Error REF 320; EXTERNAL LAG-LEAD MUST BE USED!\n");
            Laglead2=2; //lead lag for 35601A hardware, 0 to 7
            Laglead=4;  // Effective lead lag,  leadlag2 to 11
            Bwincrease=1; //       ! DON'T ALLOW LAGLEAD TO BE CHANGED

            value_i(LEADLAG,Laglead2);// ! FORCE LAGLEAD2
    }

    Lagleadcalc();

    if (forcellg2)  {value_i(LEADLAG,Laglead2);} // ! FORCE LAGLEAD2
    retrychar=0;
  do {  //this is the loop for characterization

//15745   ! CHECK TO SEE IF LOOP IS LOCKED
      Lockcheck(&Lockflag);
      if (Lockflag!=1)
        {

// ! IF NOT LOCKED, TRY TO INCREASE LOOP BANDWIDTH
            if ((Bwincrease==1) | (Laglead==0))
            {
                printf("!! Error: No lock, and cannot increase loop bandwidth any further!\n");
            } else
            {
                Laglead=Laglead-1; // !INCREASE LOOP BANDWIDTH
                printf("RETRY WITH NEW LAG LEAD CHOICE=%0.1f\n",Laglead);
                Bwincrease=1;
                Lagleadcalc();
                Lockcheck(&Lockflag);
                if (Lockflag!=1)
                {
                    printf("!! Error: No lock, even with other lag lead!\n");
                }
            }
        }

//15799 Startcharloop:         !
/*
15802    IF No_look THEN Skipplot
15805    IF Pdv<>9836 THEN Skipplot
15808    GINIT
15811    GCLEAR
15814    PEN 1
15817    GRAPHICS ON
15820    Beginexp=INT(LGT(Loopbw3)-2)
15823   !
15826    VIEWPORT 0,100,10,100
15829    LORG 5
15832    CSIZE 3,.6
15835    MOVE 70,95
15838    LABEL USING "#,K";"THEORETICAL & ACTUAL 'LOOP SUPPRESSION' FACTORS"
15841   !
15844    VIEWPORT 0,100,20,90
15847    WINDOW Beginexp,Beginexp+4,-10,10
15850    LINE TYPE 4,.30
15853    GRID 1,1,Beginexp,0
15856    LINE TYPE 1
15859    FRAME
15862    PENUP
15865 Skipplot:      !
15868   !
*/

//   ! USE 3585A FOR LOOP BANDWIDTHS >20 HZ
     if (Loopbw3<20)
        { printf("!! Warning: loop characterization for Bandwidth <20 Hz not yet implemented!\n");}

//follows: 3585 characerization

    Hzpbin=(Loopbw3*4.0/10)*0.01; // ! Span=BW3*4. Hzpbin in Units of .01 Hz.

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }
    wait_s01(3);

    sprintf(tbuf,"FB%8.1fHZ,R10,I1,SV4,S2",1000*Hzpbin);
    w3585(tbuf); //setup 3585a

//optional, to inspect:
    w3585("SV1 S1"); //save in register 1, single sweep

   // EnableLocal( BoardIndex,  PrimaryAddress3585 );                 // Local
   // if (Ibsta() & ERR) {
   //   GpibError("EnableLocal Error");
   // }

    printf("\nOBSERVE 3585 DISPLAY OF LOOP SUPRESSION CHARACTERISTIC.\n");
    printf("EXCESSIVE NOISE MAY CAUSE ACCURACY SPEC DEGRADATION \n");

    printf("CHECK LOOP SUPPRESSION ON 3585A, THEN PRESS ANY KEY\n");

    getchar();

    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }
    wait_s01(3);
    w3585("RC1"); //recall register 1
    wait_s01(10);
//end of optional section

        toggle_i(OUTOFLOCK);
        printf("\nMEASURING CLOSED LOOP RESPONSE...\n");
        wait_s01(10);

        w3585("S2"); // !Start the sweep
        waitfor3585();

        w3585("SAAB1");

        setup_i("-S3,-S4"); // ! Open loop for reference sweep

        w3585("S2"); // !Start the sweep
        waitfor3585();

        setup_i("-K7,-K6,-S2,S3,S4"); // !Close loop again

        w3585("C5CLSABO");
        rd3585();

        for (I=0;I<=1000;I++) //cut out first point which has no display data.
        {
          Display[I]=Display3585[I+1];
        }
        Display[1000]=Display[1000]&1023;
        Display[0]=Display[0]&1023;


        for (I=0;I<=1000;I++)
        {
             Display[I]=500-Display[I]; // !SCALE FROM -500 TO 500
        }

        if (Display[1000]<-10)
        {
            printf("!! Error REF309;UNABLE TO GET A VALID XFER FUNCTION FOR MEASUREMENT (<-1 dB at end of sweep)!\n");
            // !Check for < -1 dB far out
        }

        I=1001;
        do
        {
           I--;
        } while ((!(  (Display[I]<-80)&(Display[I-1]<-80)  )) | (I<2));

        printf("Found -8 dB at bin %d, %0.1f Hz\n",I,Hzpbin*I);

        if (I<2)
        {
          printf("!! Error REF309;UNABLE TO GET A VALID XFER FUNCTION FOR MEASUREMENT! <-8 dB not found!\n");
        }

        //  ! -8 dB point found, increase loop bandwidth if invalid
         if ((I>500) & (Bwincrease==0))
         {
             printf("Warning: -8 dB too far out. Trying to increase loop BW...\n");
             if (Laglead>0)
             {
                 Laglead=Laglead-1; // !INCREASE LOOP BANDWIDTH
                 printf("RETRY WITH NEW LAG LEAD CHOICE=%0.1f\n",Laglead);
                 Bwincrease=1;
                 Lagleadcalc();
                 retrychar=1;
             }
         }
    } while (retrychar);

     if (I>500)
     {
         printf("!! Error REF309;UNABLE TO GET A VALID XFER FUNCTION FOR MEASUREMENT! <-8 dB too far out!\n");
     }


}


double Freq1;                 // !Freq of first bin of 3585A display
double Freq2;                 // !Freq of 2nd bin of 3585A display
int Path;              //  !Number of the current path being checked
double Maxcorr;              //  !Max correction for a particular segment
double Maxerror;             //  !Max fit error for a particular segment
double Overallmaxcorr;        // !Max of all Maxcorr
double Overallmaxerror;      //  !Max of all Maxerror


void Calpath(void)
{
    int Display[1010]; //(-1:1000)  //

     int Reflevel;          //  !Reference level of 3585A
     int Count;             //  !Counter
    double F[100];               // !Freq's for curve fit
    double Freq;                 //  !Freq
    double Hzpbin;                // !Hz per display bin
    int I;                 //  !For-next loop counter
    int J;                  // !For-next loop counter
    int Start;             //  !Bin of display where calibration starts
    double Y[100];              //  !Amplitude for each Frequency in F(*)
    double Correction;


     w3585("MK1D2T4");
     r3585(12);
     //intf(">%s<",Buffer);
     Freq1=atof(Buffer);
     w3585("MK2D2T4");
     r3585(12);
     //intf(">%s<",Buffer);
     Freq2=atof(Buffer);
     //printf("Path: %d, Freq %0.1f  Freq2 %0.1f\n",Path,Freq1,Freq2);

     w3585("AB1 C5CL SA AB0 TA0 BO");
     rd3585();

     for (I=0;I<1001;I++)
     {
         Display[I]=Display3585[I+1]; //first bit is ffff
     }
     Display[0]=Display[0]&1023;
     Display[1000]=Display[1000]&1023;
     Reflevel=5;
     for (I=0;I<1001;I++)
     {
         Display[I]=Display[I]+(100*(Reflevel-10));
     }
     for (I=0;I<1001;I++)
     {
         Display[I]=Display[I]*(-1);
     }

     Hzpbin=Freq2-Freq1;

     Count=1;
     Start=0;
     if (Path==1) {Start=10;} // ! 2 MHz LPF
     if (Path==2) {Start=100;}
//464    IF (Plotter<>0) OR (C9835=0) THEN PENUP
     Maxcorr=-200;
     Maxerror=-200;
//4473    IF Doplot THEN LINE TYPE 1
     for (I=1;I<=81;I++)
     {
         F[I]=0;
         Y[I]=0;
     }

      for (I=Start;I<=1000;I=I+13)
      {
        Freq=I*Hzpbin+Freq1;
        F[Count]=Freq;
        Y[Count]=((double)Display[I])/100.0;
        Maxcorr=FNMax(fabs(Y[Count]),Maxcorr);
//       IF Doplot THEN PLOT LGT(Freq),Y(Count),1
        Count=Count+1;
      }

//  ! IF PATH=1 THEN ONLY GET 4 2 MHZ FILTER COEFFECIENTS

      if (Path==1)
        {
          curvefit(&F,&Y,Count-1,4,&Caldata[Path][1],&Caldata[Path][2],&Caldata[Path][3],&Caldata[Path][4],&Caldata[Path][5]);
        } else
        {
            curvefit(&F,&Y,Count-1,5,&Caldata[Path][1],&Caldata[Path][2],&Caldata[Path][3],&Caldata[Path][4],&Caldata[Path][5]);
        }

//14512    IF Doplot THEN PENUP
//14515    IF Doplot THEN LINE TYPE 3,.3

      for (I=Start;I<=1000;I=I+25)
      {
        Freq=I*Hzpbin+Freq1;
        Correction=Caldata[Path][1]+Caldata[Path][2]*Freq+Caldata[Path][3]*Freq*Freq+Caldata[Path][4]*Freq*Freq*Freq+Caldata[Path][5]/Freq;
//14527       IF Doplot THEN PLOT LGT(Freq),Correction,1
        Maxerror=FNMax(fabs((double)Display[I]/100.0-Correction),Maxerror);
      }
     Overallmaxcorr=FNMax(Maxcorr,Overallmaxcorr);
     Overallmaxerror=FNMax(Maxerror,Overallmaxerror);

}


char lf3585[2]={10,0};

void Cal(void)
{
double Amp;                 //   !Amplitude of 3585A tracking generator

char tbuf[100];
int levelok;

//    Doplot=0;//    !SET TO 0 TO SUPPRESS PLOT
//    Look=0;//      !SET TO 1 TO LOOK AT INSERTION LOSS


    printf("Calibrating interface box unflatness...\n");
    ibclr(Device3585);                 // Clear the 3585
    if (Ibsta() & ERR) {
      GpibError("ibclr Error");
    }
    wait_s01(3);

//    Mat2(C(*),"*",0,1,7,1,5)

    Caldata[7][1]=0.095;
    Caldata[7][2]=1.65E-8;
    Caldata[7][3]=-4.5E-16;
    Caldata[7][4]=5.75E-24;
    Caldata[7][5]=-5900.0;
    Overallmaxcorr=0.0;
    Overallmaxerror=0.0;
    zerolatch();
    toggle_i(OVERLOAD);
    setup_i("K2,K3,K4,K5,K7");

    w3585("AR0 AL0 RL -49DM DD1DB R01 RC4"); //setup 3585a

    levelok=0;
    do {
        w3585("S2D1T6");

        r3585(13);
        Amp=atof(Buffer);
        printf("3585A Amplitude: %0.1f dBm\n",Amp);

        if (abs(Amp+54)<=1) {levelok=1;} else
          {
            w3585("S1");
            printf("ADJUST 3585A TRACKING GEN FOR CENTER OF 3585A SCREEN, THEN PRESS KEY!\n");
            w3585("LA ADJUST 3585A TRACKING GEN FOR CENTER OF 3585A SCREEN\n");w3585(lf3585);

            getchar();
          }

      }while (!levelok);

       w3585("AL1 R05 FS FA 100000HZ FB 40.1 MZ PR RBDN DD1DB RC4 SV4 DA S1");
       w3585("LA CONNECT TG DIRECTLY TO 50 OHM INPUT");  w3585(lf3585);

       printf("CONNECT 3585A TRACKING GENERATOR OUTPUT DIRECTLY TO 3585A 50 OHM INPUT,\n THEN PRESS KEY!\n");
       getchar();

       w3585("S2 S2");
       waitfor3585();

       Path=7;

       setup_i("-K2,-K3,-K4,-K5,-K7");

       w3585("LACONNECT TG TO 40 MHZ INPUT, RECONNECT 50 OHM INPUT");w3585(lf3585);
       printf("CONNECT TRACKING GEN. TO 35601A SIGNAL INPUT, RECONNECT 50 OHM INPUT OF 3585A,\n THEN PRESS KEY!\n");

       getchar();
       printf("CALIBRATING INSERTION LOSS...\n");

       w3585("SA S2S2");

       waitfor3585();

       Calpath();

       setup_i("K2,K3,K4,K5,K7");
       w3585("AR0 AL0 RL -49DM DD1DB R01 RC4 S2 ");
//14104    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"INSERTION LOSS",Maxcorr,Maxerror
       printf(">>Insertion Loss %0.3f %0.3f\n\n",Maxcorr,Maxerror);
       printf("RECONNECT 3585A TRACKING GEN. TO 35601A TRACKING GEN. INPUT,\n THEN PRESS KEY!\n");
       w3585("TB0TA1LARECONNECT TRACKING GENERATOR TO PROPER 35601A CONNECTION");w3585(lf3585);

       getchar();

//Path1: !
        printf("CALIBRATING AMPLIFIER FLATNESS; RESULTS ARE [MAXCORR] [MAXERROR]\n");
//  ! CALIBRATE 2 MHZ LOW PASS FILTER ON HF BOARD TO 1MHz
        Path=1;
        setup_i("K1,K12");
        w3585("RL -49DM FA0HZ FB1MZ PR RBDN RC4 SV4 DA S2 S2");
        w3585("LA 2MHZ FILTER IN");w3585(lf3585);
        waitfor3585();
        setup_i("K8"); // !K8 AND K9 MOVE TOGETHER
        w3585("SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>2 MHz Filter %0.3f %0.3f\n",Maxcorr,Maxerror);

//14161    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"2 MHz FILTER",Maxcorr,Maxerror

//14167  ! CALIBRATE AMPLIFIER PATH TO 400 HZ
        Path=2;
        setup_i("-K8,-K9");
        w3585("FA5HZ FB405HZ PR RC4 SV4 TB0  S2 S2");
        w3585("LA STRAIGHT THROUGH, AMPLIFIER IN");w3585(lf3585);
        waitfor3585();
        setup_i("K11");
        w3585("RL -15DM SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>x100 AMP to 400 Hz %0.3f %0.3f\n",Maxcorr,Maxerror);

//14197    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"x100 AMP TO 400 Hz",Maxcorr,Maxerror

//  ! CALIBRATE AMPLIFIER PATH FROM 400 TO 25000 HZ
        Path=3;
        setup_i("-K11");
        w3585("RL-49DM FA400HZ FB25400HZ PR RBDN RC4 SV4 TB0 S2 S2");
        waitfor3585();

        setup_i("K11");
        w3585("RL -15DM SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>x100 AMP 400 TO 25 KHz %0.3f %0.3f\n",Maxcorr,Maxerror);


//14230    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"x100 AMP 400 TO 25 KHz",Maxcorr,Maxerror

//  ! CALIBRATE AMPLIFIER FROM 25000 TO 5 MHz
        Path=4;
        setup_i("-K11");
        w3585("RL -49DM FA 25000HZ FB 5000000  HZ PR RBDN RC4 SV4 TB0 S2 S2");
        w3585("LA STRAIGHT THROUGH, AMPLIFIER IN         ");w3585(lf3585);
        waitfor3585();

        setup_i("K11");
        w3585("RL -15DM SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>x100 AMP 25 KHz TO 5 MHz %0.3f %0.3f\n",Maxcorr,Maxerror);


//14266    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"x100 AMP 25 KHz TO 5 MHz",Maxcorr,Maxerror
        Path=5;
        setup_i("-K11");
        w3585("RL -49DM FA 5000000HZ FB 40000000HZ PR RBDN RC4 SV4 TB0 S2 S2");
        w3585("LA STRAIGHT THROUGH, AMPLIFIER IN         ");w3585(lf3585);
        waitfor3585();

        setup_i("K11");
        w3585("RL -15DM SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>x100 AMP 5 MHz TO 40 MHz %0.3f %0.3f\n",Maxcorr,Maxerror);



//14296    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"x100 AMP 5 MHz TO 40 MHz",Maxcorr,Maxerror

//  ! CALIBRATE STRAIGHT THROUGH PATH (NO AMP) FROM 25000 TO 40 MHz
        Path=6;
        setup_i("-K1,-K11,-K12");
        w3585("RL -49DM FA 25000HZ FB 40000000HZ PR RBDN RC4 SV4 TB0 S2 S2");
        w3585("LA STRAIGHT THROUGH, AMPLIFIER OUT        ");w3585(lf3585);
        waitfor3585();

        setup_i("K1,K12");
        w3585("SA S2 S2");
        waitfor3585();

        Calpath();
        printf(">>STRAIGHT 25 KHz TO 40 MHz %0.3f %0.3f\n",Maxcorr,Maxerror);


        setup_i("-K1,-K12");
//14332    OUTPUT Printer USING "25A,7X,DD.DDD,14X,DD.DDD";"STRAIGHT 25 KHz TO 40 MHz",Maxcorr,Maxerror
//14338    BEEP
//14341    IF Look=0 THEN GOTO No_output
//14344    OUTPUT Printer USING "//,K,K";".02 TO 40 Hz AMPLIFIER CORRECTION WILL BE:",C(2,1)+C(2,2)*40+C(2,3)*1600+C(2,4)*40^3+C(2,5)/40
//14347    OUTPUT Printer USING "//,5(K,3X)";"INSERTION LOSS COEFFECIENTS:",C(7,1),C(7,2),C(7,3),C(7,4),C(7,5)
//14350 ! OUTPUT Printer USING "///";
//14353 No_output:!
//14356    IF (Printer<>0) AND (Doplot=1) THEN DUMP GRAPHICS

        printf(">> 0.02 TO 40 Hz AMPLIFIER CORRECTION WILL BE: %0.5f\n",Caldata[2][1]+Caldata[2][2]*40+Caldata[2][3]*1600+Caldata[2][4]*40*40*40+Caldata[2][5]/40);
        printf("\nINSERTION LOSS COEFFICIENTS:\n%0.4e %0.4e %0.4e %0.4e %0.4e\n",Caldata[7][1],Caldata[7][2],Caldata[7][3],Caldata[7][4],Caldata[7][5]);


        zerolatch();
        setup_i("F0");

         if ((Overallmaxerror>1.0) | (Overallmaxcorr>=3.5))
         {
             printf("!! Error REF 317; UNABLE TO CALIBRATE 35601A\n");
         } else
         {
             printf("\n35601A calibration complete!\n\n");
         }



}

/*
16858    ! *  NAME: Phioff
16864    ! *  FUNCTION: Calculate the correction factors for a particular
16867    ! *            segment of data.
16873    ! *  INPUT:   Plotindex, Vcoindex, Amplifier,
16876    ! *           Mixerfreq, Caldata(*), W1, W2, W3, Loopbw1, Phaseslope,
16879    ! *           Vcoslope, Vcofreq
16885    ! *  OUTPUT:  Plotdata(*)
*/
// note: Caldata needs to contain current cal data to be used (not necessarily the C cal data determined by Cal!
void Phioff(int Plotdata[][1012], int Plotindex,int Vcoindex,int Measuretype,int Amplifier,double Mixerfreq,double W1,double W2,double W3,double Loopbw1,double Phaseslope,double Vcoslope,double Vcofreq)
{
    double Ang;    //                    !Phase angle of loop correction
    double Bwcorr;    //                 !Bandwidth correction
    double C1,C2,C3,C4,C5;    //         !Signal path correction coeffecients
    int Calnum;    //              !Index into Caldata(*) for coeffecients
    double Corr;    //                   !Correction- bwcorr,phaseslope or vcoslope & gain
    int Cutoff;    //              !Index beyond which loop corrections=0
    double F;    //                      !Freq in Hz
    double Fw;    //                     !F(w), loop correction factor
    int Gain;    //                !Gain from low noise amp
    double Hzpbin;    //                 !Number of Hz per data point
    int I;    //                   !For-next loop counter
    int Maxi;    //                !Max number of points to calibrate
    double Pole;    //
    double R;    //                      !Magnitude of loop correction
    double Rc2pi;    //                  !(R*C*2PI)^2 used in AC COUPLER correction
    double W;    //                      !Freq in radians/sec
    double W5;    //                     !Lead freq in lead-lag
    double Wloopbw1;    //               !Loop bandwidth
    double Ww;    //                     !W  squared
    double Ww1;    //                    !W1 squared
    double Ww2;    //                    !W2 squared
    double Ww3;    //                    !W3 squared
    double Ww5;    //

    int Phioffdone;

    printf("Calculating Phi offset...\n");

//      ! Measuretype 0 -- vco control
//      !   Vcoslope#0  Phaseslope#0   Loopbw1#0  Loopbw3#0
//      !
//      ! Measuretype 1 -- no vco control
//      !   Vcolsope=0  Phaseslope#0   Loopbw1=0  Loopbw3=0
//      !
//      ! Measuretype 2 -- discriminator
//      !   Vcolsope#0  Phaseslope=0   Loopbw1=0  Loopbw3=0

    Phioffdone=0;
    Rc2pi=(1.0E+5*1.0E-5*2.0*M_PI)*(1.0E+5*1.0E-5*2.0*M_PI);

    Plotdata[Plotindex][1007]=2; //valid data flag - corrected data

    if (Plotindex<=10)
    {
        //**3582 Hzpbin=((double)(Plotdata[Plotindex][1010]))/250.0; //these variables are set by getdata

        Hzpbin=((double)(Plotdata[Plotindex][1010]))/800.0; //these variables are set by getdata

        //**3562 Bwcorr=-10.0*log10(363.0/(25000.0/Plotdata[Plotindex][1010]));

        Bwcorr=-10.0*log10(119.0/(25000.0/((double)Plotdata[Plotindex][1010])));//this is for the 3562a

        if (Plotindex<=Vcoindex)
        {
           // AC COUPLER CORRECTION: (HIGH PASS FILTER)
           // HPF : 1/(1+1/RCs)
           // HPF CORRECTION : 1+1/RCs
           // 10*LGT( |1+1/RCs| ^2 )
           // 10*LGT(1+1/(RCW)^2)
           //
           // LAG LEAD : (1+s/W2)/(1+s/W3)
           // 10*LGT( |1+s/W3|^2 / |1+s/W3|^2 )
           // 10*LGT( (1+(W/W2)^2) / (1+(W/W3)^2))
           // where W=(2*PI*F)
           //
           // LEAD: (1+s/W5) -> 10*LGT(|1+s/W5|^2)  -> 10*LGT(1+(W/W5)^2)
           // COMBINING ALL TERMS:
           // 10*LGT( (1+1/(RCW)^2) * (1+(W/W5)^2) * (1+(W/W2)^2) / (1+(W/W3)^2) )
           // RC=100K*10uF =1

            W5=2.0*M_PI*33500.0;
            Ww2=W2*W2;
            Ww3=W3*W3;
            Ww5=W5*W5;

            Corr=10.0*(C1+Bwcorr+20.0*log10(fabs(Vcoslope)));

            //**for (I=1;I<=255;I++)
            for (I=1;I<=800;I++)
            {
                F=I*Hzpbin;
                Ww=2.0*M_PI*2.0*M_PI*F*F;
                Plotdata[Plotindex][I]=(int)(Corr-10*20*log10(F)+10*10*log10((1+1/Ww)*(1+Ww/Ww5)*(1+Ww/Ww2)/(1+Ww/Ww3)));
            }
            printf("Phioff: Plotindex<=VCOindex Correction done!\n");
            Phioffdone=1;
        } else
        {
            Cutoff=(int)(Vcofreq*40/Hzpbin);
            //**3562 Cutoff=(int)FNMin(255,(double)(Cutoff));
            Cutoff=(int)FNMin(800.0,(double)(Cutoff));
            Cutoff=(int)FNMax(0,(double)(Cutoff));
            Gain=40;
            //**3562 Maxi=255;
            Maxi=800;
            printf("Cutoff (LF) %i\n",Cutoff);
        }
    }
      else
    {

        if (Plotindex==11) {Bwcorr=-27.96-0.5;}//    !-.5 IS FOR PEAK DETECT CORRECTION
        if (Plotindex==12) {Bwcorr=-37.96;}   //    !-10*LGT(BW)+2.03857
        if (Plotindex==13) {Bwcorr=-42.73;}  //
        Hzpbin=((double)Plotdata[Plotindex][1010])*10.0;
        Gain=40-6;
        Cutoff=(int)(FNMin(1000.0,Vcofreq*70.0/Hzpbin));
        Cutoff=(int)FNMax((double)(Cutoff),0);
        Maxi=1000;
        printf("Cutoff (HF) %i\n",Cutoff);
    }

    if (!Phioffdone)
    {

//17071 Fwcalc:     !
//      ! CALDATA DEFINITION
//      ! 1) 0-1 MHz     2MHz filter
//      ! 2) 0-400 Hz    amplifier
//      ! 3) 400-25KHz   amplifier
//      ! 4) 25KHz-5MHz  amplifier
//      ! 5) 5KHz-40MHz  amplifier
//      ! 6) 5MHz-40MHz no amplifier
//      ! 7) Insertion loss

    C1=0;
    C2=0;
    C3=0;
    C4=0;
    C5=0;
    if (Amplifier==0) {Gain=0;}

    if (!(Mixerfreq>=9.5E+7))
    {
        C1=Caldata[1][1];//     !2 MHz filter correction
        C2=Caldata[1][2];
        C3=Caldata[1][3];
        C4=Caldata[1][4];//     !NO C5 FOR FILTER
    }

    if (Amplifier!=0)
    {

        if (Plotindex<=4)
        {
            C1=C1+Caldata[2][1]+Caldata[2][2]*40.0+Caldata[2][3]*1600.0+Caldata[2][4]*64000.0+Caldata[2][5]/40.0;
                // ! Calibrate amplifier for freqs < 40 Hz
        }
        else
        {
            if (Plotindex==13) {Calnum=5;}     // Amplifier 5 MHz to 40 MHz
            if (Plotindex==12) {Calnum=4;}     // Amplifier 25 KHz to 5 MHz
            if (Plotindex==11) {Calnum=4;}     // Amplifier 25 KHz to 5 MHz
            //**3582 if (Plotindex<=10) {Calnum=3;}    // Amplifier 400 Hz to 25 KHz
            //**3582 if (Plotindex<=6) {Calnum=2;}     // Amplifier 40 Hz to 400 Hz

            if (Plotindex<=10) {Calnum=3;}    // Amplifier 400 Hz to 25 KHz
            if (Plotindex<=7) {Calnum=2;}     // Amplifier 40 Hz to 400 Hz

            C1=C1+Caldata[Calnum][1];
            C2=C2+Caldata[Calnum][2];
            C3=C3+Caldata[Calnum][3];
            C4=C4+Caldata[Calnum][4];
            C5=C5+Caldata[Calnum][5];
        }

    }

 //  Calibrate insertion loss
    C1=C1+Caldata[7][1]+Caldata[6][1];

    if (!(Plotindex<=10))
    {
        C2=C2+Caldata[7][2]+Caldata[6][2];
        C3=C3+Caldata[7][3]+Caldata[6][3];
        C4=C4+Caldata[7][4]+Caldata[6][4];
        C5=C5+Caldata[7][5]+Caldata[6][5];
    }


// do the actual data correction
    if (Measuretype==0)
    {
        Ww1=W1*W1;
        Ww2=W2*W2;
        Ww3=W3*W3;
        Wloopbw1=2.0*M_PI*Loopbw1;
        Corr=10.0*(Bwcorr-20.0*log10(Phaseslope)-(double)Gain);

        printf("C[I] %e %e %e %e %e\n",C1,C2,C3,C4,C5);
        printf("BWcorr %0.3f\n",Bwcorr);
        printf("Phaseslope corr %0.3f\n",-20.0*log10(Phaseslope));
        printf("Gain corr %0.3f\n",-(double)Gain);
        printf("Corr %0.3f\n",Corr/10);
        printf("Hzpbin %0.3f\n",Hzpbin);
        printf("Plotindex %i\n",Plotindex);
        printf("Hz Stopindex %0.3f\n",Hzpbin*((double)Plotdata[Plotindex][1009]));


        for (I=1; I<=Cutoff; I++)
        {
            F=I*Hzpbin;
            W=2.0*M_PI*F;
            Ww=W*W;
          //  W0=1/2   W0^2=.25
            R=Wloopbw1/W*sqrt((1+Ww/Ww2)*(1.0+0.25/Ww)/((1.0+Ww/Ww3)*(1.0+Ww/Ww1)));
            Pole=W/1.75E+6;
            if (Pole>(M_PI/2.0)) {Pole=M_PI/2.0;}
            Ang=-atan(W/W1)+atan(W/W2)-atan(W/W3)-M_PI/2.0-atan(0.5/W)-Pole;
            Fw=-10.0*log10(1.0+2.0*R*cos(Ang)+R*R);
            F=FNMax(F,Hzpbin*((double)Plotdata[Plotindex][1009])); //stopindex stored in 1009
            Plotdata[Plotindex][I]=(int)(Corr-10.0*Fw+10.0*(C5/F+C1+F*(C2+F*(C3+F*C4))));
            //**3562 needs to be checked
            if (Plotindex<=2) {Plotdata[Plotindex][I]=Plotdata[Plotindex][I]+(int)(100.0*log10(1.0+1.0/Ww));}
        }

        for (I=Cutoff+1;I<=Maxi;I++)
        {
            F=I*Hzpbin;
            F=FNMax(F,Hzpbin*(double)(Plotdata[Plotindex][1009]));
            Plotdata[Plotindex][I]=(int)(Corr+10*(C5/F+C1+F*(C2+F*(C3+F*C4))));

            //**3562 needs to be checked
            if (Plotindex<=2) {Plotdata[Plotindex][I]=Plotdata[Plotindex][I]+(int)(100.0*log10(1.0+1.0/(Rc2pi*F*F)));}
        }

    }
   else
//Cal no vco
    if (Measuretype==1)
    {
        Corr=10*(Bwcorr-20*log10(Phaseslope)-Gain);
        for (I=1;I<=Maxi;I++)
        {
            F=I*Hzpbin;
            F=FNMax(F,Hzpbin*(Plotdata[Plotindex][1009]));
            Plotdata[Plotindex][I]=Corr+10.0*(C5/F+C1+F*(C2+F*(C3+F*C4)));
            if (Plotindex<=2) {Plotdata[Plotindex][I]=Plotdata[Plotindex][I]+100.0*log10(1.0+1.0/(Rc2pi*F*F));}
        }
    }
   else
//Cal discrim
    if (Measuretype==2)
    {

     //  VCOSLOPE IS THE RECIPROCAL OF THE DISCRIMINATOR CONSTANT
     //  S PHI(F)=V^2 * (Hz/V)^2 / F^2  = S NU / F^2

        Corr=10.0*(Bwcorr+20.0*log10(Vcoslope)-Gain);
        for (I=1;I<=Maxi;I++)
        {
            F=I*Hzpbin;
            F=FNMax(F,Hzpbin*(Plotdata[Plotindex][1009]));
            Plotdata[Plotindex][I]=Corr+10.0*(-20.0*log10((double)I*Hzpbin)+C5/F+C1+F*(C2+F*(C3+F*C4)));
            if (Plotindex<=2) {Plotdata[Plotindex][I]=Plotdata[Plotindex][I]+100.0*log10(1.0+1.0/(Rc2pi*F*F));}
        }
    }
   else
    {
        printf("!! Error: Unknown measurement type: %d\n",Measuretype);
    }

   }
}


#define C_Phaseslope 0
#define C_Gain1 1
#define C_Gain2 2
#define C_Atten1 3
#define C_Atten2 4
#define C_Vcoslope 5
#define C_Vpeak 6
#define C_DAC 7


void writef_cal(char fname[100])
{
    calparameters[C_Phaseslope]=Phaseslope;
    calparameters[C_Vcoslope]=Vcoslope;
    calparameters[C_Vpeak]=Vpeak;

    FILE *f = fopen(fname, "wb");
    printf("Storing cal data in file %s ...",fname);
    fwrite(caltexts, sizeof(char), sizeof(caltexts), f);
    fwrite(calparameters, sizeof(char), sizeof(calparameters), f);
    fwrite(Caldata, sizeof(char), sizeof(Caldata), f);
    fclose(f);
    printf(" Done.\n");
}

void readf_cal(char fname[100])
{
    FILE *f = fopen(fname, "r");
    printf("Reading cal data from file %s ...",fname);
    fread(caltexts, sizeof(char), sizeof(caltexts), f);
    fread(calparameters, sizeof(char), sizeof(calparameters), f);
    fread(Caldata, sizeof(char), sizeof(Caldata), f);
    fclose(f);
    printf(" Done.\n");

    Phaseslope=calparameters[C_Phaseslope];
    Vcoslope=calparameters[C_Vcoslope];
    Vpeak=calparameters[C_Vpeak];

    printf("VCOSLOPE=%e Hz/V\n",Vcoslope/Atten1);
    printf("PHASESLOPE=%e V/rad\n",Phaseslope);
    printf("VPEAK=%0.2f V\n",Vpeak);


}


void writef_trace(char fname[100])
{
    FILE *f = fopen(fname, "wb");
    printf("Storing trace data in file %s ...",fname);
    fwrite(tracetexts, sizeof(char), sizeof(tracetexts), f);
    fwrite(traceparameters, sizeof(char), sizeof(traceparameters), f);
    fwrite(tracedata, sizeof(char), sizeof(tracedata), f);
    fclose(f);
    printf(" Done.\n");
}

void writef_tracetxt(char fname[100])
{
    int I,J;
    int startbin,stopbin;
    double hzpbin;
    double freq;

    FILE *f = fopen(fname, "wb");
    printf("Storing trace data (text) in file %s ...",fname);

    //fwrite(traceparameters, sizeof(char), sizeof(traceparameters), f);
    //fwrite(traceparameters, sizeof(char), sizeof(traceparameters), f);
    fprintf(f,"PHASE NOISE TRACE DATA\n");
    for (I=1;I<=13;I++)
    {
        if (tracedata[I][1007]>0.1) //valid segment
        {

            if (I>=11)
            {
                startbin=P85[I][1008];
                stopbin=P85[I][1009];
                hzpbin=(double)P85[I][1010];
            } else
            {
                startbin=P82[I][1008];
                stopbin=P82[I][1009];
                hzpbin=(double)P82[I][1010];
            }


            if (I>10) {hzpbin=hzpbin*10;} else
                //{hzpbin=hzpbin/250;}
                {hzpbin=hzpbin/800.0;}

            //fprintf(f,"SEG %i\n",I);
            //printf("%i %i %i\n",I,startbin,stopbin);
            //printf("%i %i %i\n",I,P85[I][0],P85[I][1]);

            for (J=startbin;J<=stopbin;J++)
            {
                freq=hzpbin*(double)J;
             //   fprintf(f,"TRA: %i: %0.3f Hz, %0.2f dBc\n",J-startbin,freq,tracedata[I][J]);
              if (I>=11)
              {
                fprintf(f,"%i %i %0.2f %0.1f %0.1f %0.1f\n",I,J-startbin,freq,tracedata[I][J],0.1*(double)P85_C[I][J],tracedata[I][J]+0.1*(double)P85_C[I][J]);
              } else
              {
                 fprintf(f,"%i %i %0.2f %0.1f %0.1f %0.1f\n",I,J-startbin,freq,tracedata[I][J],0.1*(double)P82_C[I][J],tracedata[I][J]+0.1*(double)P82_C[I][J]);
              }

            }
        }
    }
    //fwrite(tracedata, sizeof(char), sizeof(tracedata), f);
    fprintf(f,"EOF\n");
    fclose(f);
    printf(" Done.\n");
}

int Measuretype_t, Caltype_t;

void do_trace_corr()  //calculated trace data from valid P82, P85 data
{
   int I,J;

//for the 3562a data
   for (I=3;I<=10;I++)  //segment 3 is lowest segment fo 3562a
   {
       if (P82[I][1007]==1)
       {
            P82_C[I][1008]=P82[I][1008];
            P82_C[I][1009]=P82[I][1009];
            P82_C[I][1010]=P82[I][1010];
            printf("Correction... LF Segment %i\n",I);
            Phioff(P82_C,I,Vcoindex,Measuretype_t,Amplifier,Mixer,W1,W2,W3,Loopbw1,Phaseslope,Vcoslope,Vcofreq);
       }
   }

   for (I=3;I<=10;I++)
   {
       if (P82[I][1007]==1) //valid data
       {
           for(J=0;J<=800;J++)
           {
                tracedata[I][J]=((double)P82[I][J])/10.0;
           }
           tracedata[I][1007]=1.0; //valid data
       }

   }


   //Phioff(int Plotdata[][1012], int Plotindex,int Vcoindex,int Measuretype,int Amplifier,double Mixerfreq,double W1,double W2,double W3,double Loopbw1,double Phaseslope,double Vcoslope,double Vcofreq)
   for (I=11;I<=13;I++)
   {
       if (P85[I][1007]==1)
       {
            P85_C[I][1008]=P85[I][1008];
            P85_C[I][1009]=P85[I][1009];
            P85_C[I][1010]=P85[I][1010];
            printf("Correction... HF Segment %i\n",I);
            Phioff(P85_C,I,Vcoindex,Measuretype_t,Amplifier,Mixer,W1,W2,W3,Loopbw1,Phaseslope,Vcoslope,Vcofreq);
       }
   }

   for (I=11;I<=13;I++)
   {
       if (P85[I][1007]==1) //valid data
       {
           for(J=0;J<=1000;J++)
           {
                tracedata[I][J]=((double)P85[I][J])/10.0;
           }
           tracedata[I][1007]=1.0; //valid data
       }

   }


}



void w3562(char *buf)
{

   ibwrt(Device3562, buf, strlen(buf));


   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}


void w3562b(char *buf, int len)
{

   ibwrt(Device3562, buf, len);


   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}

void w3562d(char *buf) //for debug only
{

    printf("Command: >%s<\n",buf);
    printf("Length: %i bytes\n",strlen(buf));
   ibwrt(Device3562, buf, strlen(buf));


   if (Ibsta() & ERR) {
      GpibError("ibwrt Error");
   }
}

void r3562(int cnt)
{
   ibrd(Device3562, Buffer, cnt); //read

   if (Ibsta() & ERR) {
      GpibError("ibrd Error");
   }
}


unsigned char Display3562[20000];
double Display3562t[810]; //0 to 800, 801 data points
double Display3562p[80]; //parameters

double Display3562bn[10000]; //binary

void rd3562(int len)
{
   ibrd(Device3562, Display3562, len); //read

   if (Ibsta() & ERR) {
      GpibError("ibrd Error");
   }

}

void rd3562b(int len)
{
   ibrd(Device3562, Display3562bn, len); //read

   if (Ibsta() & ERR) {
      GpibError("ibrd Error");
   }

}
char istate3562[1000];//instrument state
int istate3562_set=0;


void i3562_savestate(void)
{
   int i;

   int datal;

   w3562("DSAN");
   r3562(4);
   //printf("%c %c\n",Buffer[0],Buffer[1]);
   datal=Buffer[2];
   datal=datal<<8;
   datal|=Buffer[3];
   istate3562[0]=Buffer[2];//length data
   istate3562[1]=Buffer[3];//length data
   printf("3562A: %i bytes state dump received\n",datal);
   r3562(datal);
   if (datal==768)
   {
        for (i=0;i<datal;i++)
        {
            //printf("%2x",Buffer[i]);
            istate3562[i+2]=Buffer[i];

        }
        istate3562_set=datal;

        printf("Save 3562A state OK.\n");
   }else
   {
        printf("!!Error: 3562A state dump has incorrect length!\n");
        istate3562_set=0;
   }
}

void i3562_recallstate(void)
{
   if (istate3562_set>0)
   {
        w3562("LSAN#A");
        w3562b(istate3562,istate3562_set+2);//dump 2 bytes length and 768 bytes state data
        printf("Recalled 3562A state OK.\n");

   } else
   {
       printf("!! Error: Cannot recall 3562A state - no state saved.\n");
   }
}

int rangelevel3562[11]={0,0,27,20,10,0,-10,-20,-30,-40,-50}; //values in dbvrms

char range_s3562[20];
int range_3562;


double i3562_irtodouble(int i) //convert 3562 internal float to double
{
   long int m_t;
   int e_t;
    double d1,d2,d3;

       m_t=(Display3562[i]<<16)|(Display3562[i+1]<<8)|(Display3562[i+2]);
       e_t=(signed char) Display3562[i+3];
       d1=(double)(m_t&0x7fffff);
       if ((m_t&0x800000)==0x800000)
       {
           d1=-(8388608.0-d1); //0x800000 hex 2 complements
       }

       d2=(double)e_t;
       d3=pow(2,e_t)*d1/pow(2,23);
       return d3;
}

void i3562_autorange(void)
{

   int i,j;
   unsigned long LocalIbsta;
   char SpollByte;

   ibclr(Device3562);                 /* Clear the device                        */


  //w3562("PRST;LNRS;PSP2;FLAT;FLT1;FLT2;MGDB;PSPC;AUTO0;CH2;");
  w3562("AVOF;");
  w3562("SRQE;ISM64;");
  w3562("FRS100kHz;");
  printf("3562 autorange... dBVrms = ");
  i=2; // 2 is highest range
  j=0;
  do
  {

    sprintf(range_s3562,"C2RG%iDBV;",rangelevel3562[i]);
    w3562(range_s3562); //set range

    w3562("STRT"); //start, otherwise it doesn't sense overrange

    wait_s01(30);

    LocalIbsta = ibrsp (Device3562, &SpollByte);
    if (LocalIbsta & ERR) {
            printf ("\n!!Error: ibrsp failed. No more callbacks.\n");
        }
    //printf("%x \n",(unsigned char)SpollByte);
    printf("%i ",rangelevel3562[i]);

    if ((SpollByte&0x8f)==0x0b)//status change
    {
        w3562("SOV2;");
        r3562(1);
        //printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);
        if (Buffer[0]==0x32)
        {
            printf(" Overload!");
            j=200;
        }


    } else { wait_s01(10);} //spoll every 1 s
    i++;
  } while (!((i>=11)|(j==200))); //no more than 100 seconds
  if (i==11) { if (j!=200){j=200;i=12;}};//if overrange is not reached in 10th range, set to 10th.
  i=i-2;
  if (j!=200)
  {
      printf("\n!!Error: 3562A autorange not complete!\n");
      range_3562=0;
  } else
  {
      printf("\n3562 autorange complete. Range: %i, %i\n",i,rangelevel3562[i]);
      range_3562=i;
  }

}

void i3562_setrange_c2(int range_i)//ranges 2 to 10
{

  ibclr(Device3562);                 /* Clear the device                        */

  sprintf(range_s3562,"C2RG%iDBV;",rangelevel3562[range_i]);

  w3562(range_s3562); //set range
}


void i3562_pwrspec_init(void)  //init for pwr spectrum
{
   ibclr(Device3562);                 /* Clear the device                        */

   w3562("PRST;LNRS;PSP2;FLAT;FLT1;FLT2;MGDB;PSPC;AUTO0;CH2;STBL;PSUN;VTRM;VLTS;");
   w3562("YSCL-150,10DB;");
   wait_s01(50);

   w3562("NAVG1ENT;");//1 avg stable mean
   w3562("FRS1000Hz;C2RG3DBV;");
   w3562("SRQE;ISM4;");//enable SRQ and set end of meas mask
   w3562("STRT");//run to acquire some dummy data

}



void i3562_pwrspec(int segment_i,int range_i, int avg_i)  //acquire pwr spectrum
{
   unsigned long LocalIbsta;
   char SpollByte;

   time_t t;
   int i,j,c1,c2,k;
   char t_s[100];
   char tbuf[100];
   int datal,datal2;
   double d_t,d1,d2,d3;

   double maxrange,perdiv;

   long int m_t;
   int e_t;

   int timeout;


   ibclr(Device3562);                 /* Clear the device                        */

   sprintf(tbuf,"NAVG%iENT;FRS%iHz;C2RG%iDBV;",avg_i,P[segment_i][2],rangelevel3562[range_i]);
   w3562d(tbuf);

   w3562("SRQE;ISM4;");//enable SRQ and set end of meas mask
   w3562("STRT");


   if (segment_i>6) {timeout=10;} else {timeout=100;} //1 s or 10 s timeout

   //getchar();
  i=0;
  do
  {
    LocalIbsta = ibrsp (Device3562, &SpollByte);
    if (LocalIbsta & ERR) {
            printf ("!!Error:ibrsp failed. No more callbacks.\n");

        }
    printf("%x ",(unsigned char)SpollByte);
      //w3562("IS?");
      //rd3562(2);
      //printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);

    if ((SpollByte&0x8f)==0x0b)//status change
    {
        w3562("IS?;");
        r3562(2);
        printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);
        //printf("%x %x\n",(unsigned char)Buffer[0]&0x04,(unsigned char)Buffer[1]);

        if ((Buffer[1]&0x04)==0x04)
        {

            i=200;
        } else {i=300;}//some other SRQ must have occured


    } else { wait_s01(timeout);} //spoll every 1 s or 10 s
     i++;
  } while (i<150); //no more than 150 //1500 seconds

  if (i!=201)
  {
      printf("!!Error: 3562A acquisition timeout! %i\n",i);
  } else {printf("3562A: Acquisition complete!\n");}

  ibclr(Device3562);                 /* Clear the device                        */

   w3562("DDBN");  //dump binary
   r3562(4);
   datal=Buffer[2];
   datal=datal<<8;
   datal|=Buffer[3];
   printf("3562A: %i bytes binary data dump received\n\n",datal);
   rd3562(datal);
   c1=0;
   for (i=168;i<datal;i=i+4)
   {
       m_t=(Display3562[i]<<16)|(Display3562[i+1]<<8)|(Display3562[i+2]);
       e_t=(signed char) Display3562[i+3];
       d1=(double)(m_t&0x7fffff);
       d2=(double)e_t;
       d3=pow(2,e_t)*m_t/pow(2,23);
       //printf("%i, %i %i   %2x %2x %2x  %e\n",c1,m_t,e_t,Display3562[i],Display3562[i+1],Display3562[i+2],d3);
       Display3562t[c1]=d3;
       c1++;
    }
    if (c1!=801)
    {
        printf("!!Error: Did not receive 801 points for trace! %i points received!\n",c1);
    } else
    {
        printf("Trace received OK. 801 points.\n");

        for (i=0;i<10;i++)
        {
            printf("%3i: %e ",i,Display3562t[i]);
            printf("%3i: %4.2f ",i,20.0*log10(Display3562t[i]));
        }

        perdiv=i3562_irtodouble((59<<1)-2);
        maxrange=i3562_irtodouble((61<<1)-2);
        printf("\n Hz per div: %0.2e, V maxrange: %0.2e, fullx Hz: %0.3f\n",perdiv,maxrange,perdiv*800.0);

        for (i=0;i<=800;i++)
        {
            P82[segment_i][i]=(int)(10.0*20.0*log10(Display3562t[i]));            //values in dbVrms (x10)
        }
        P82[segment_i][1007]=1; //valid trace
    }


}


void i3562_timeb(void)  //acquire time buffer
{
   unsigned long LocalIbsta;
   char SpollByte;

   time_t t;
   int i,j,c1,c2,k;
   char t_s[100];
   int datal,datal2;
   double d_t;
   double maxrange,perdiv;


   ibclr(Device3562);                 /* Clear the device                        */

   //w3562("RST");

   w3562("PRST;AVOF;AUTO0;CH2;REAL;FILT;TMR2;TLN200MSEC;");
   //w3562("FRS1000Hz;C2RG3DBV;");

   w3562("SRQE;ISM4;");//enable SRQ and set end of meas mask
   w3562("STRT");
  // wait_s01(40);
  // w3562("STRT");

   //w3562("STRT");



   //getchar();
  i=0;
  do
  {
    LocalIbsta = ibrsp (Device3562, &SpollByte);
    if (LocalIbsta & ERR) {
            printf ("!!Error:ibrsp failed. No more callbacks.\n");

        }
      printf(".");
    //printf("%x \n",(unsigned char)SpollByte);
      //w3562("IS?");
      //rd3562(2);
      //printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);

    if ((SpollByte&0x8f)==0x0b)//status change
    {
        w3562("IS?;");
        r3562(2);
        //printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);
        //printf("%x %x\n",(unsigned char)Buffer[0]&0x04,(unsigned char)Buffer[1]);

     //   if ((Buffer[1]&0x04)==0x04)
      //  {

            i=200;
      //  } else {i=300;}//some other SRQ must have occured


    } else { wait_s01(10);} //spoll every 1 s
     i++;
  } while (i<100); //no more than 100 seconds

  if (i!=201)
  {
      printf("!!Error: 3562A acquisition timeout! %i\n",i);
  } else {printf("3562A: Acquisition complete!\n");}

  ibclr(Device3562);                 /* Clear the device                        */


  //w3562("PRST;LNRS;PSP2;FLAT;FLT1;FLT2;MGDB;PSPC;AUTO0;CH2;");



 // getchar();



   w3562("DDBN");  //DDAN
   r3562(4);
   datal=(unsigned char)Buffer[2];
   datal=datal<<8;
   datal|=(unsigned char)Buffer[3];
   //printf("%x %x\n",(unsigned char)Buffer[0],(unsigned char)Buffer[1]);
   //printf("%x %x\n",(unsigned char)Buffer[2],(unsigned char)Buffer[3]);
   printf("3562A: %i bytes binary data dump received\n\n",datal);
   rd3562(datal);

   perdiv=i3562_irtodouble((59<<1)-2);
   maxrange=i3562_irtodouble((61<<1)-2);
   printf(" per div: %e, maxrange: %e, fullx: %f\n",perdiv,maxrange,perdiv*2048.0);

//   for (i=(53<<1);i<168;i=i+4)
//   {
//     printf("%i: %e\n",i/2,i3562_irtodouble(i-2));
//   }


   c1=0;
   for (i=168;i<datal;i=i+4)
   {

       //printf("%i, %i %i   %2x %2x %2x  %e\n",c1,m_t,e_t,Display3562[i],Display3562[i+1],Display3562[i+2],d3);
       Display3562t[c1]=i3562_irtodouble(i);
       c1++;
    }
    if (c1!=2048)
    {
        printf("!!Error: Did not receive 2048 points for trace! %i points received!\n",c1);
    } else
    {
        printf("Trace received OK. 2048 points.\n");

        for (i=0;i<2047;i++)
        {
           if ((Display3562t[i]>0)&&(Display3562t[i+1]<0)) printf("-: %i ",i);
           if ((Display3562t[i]<0)&&(Display3562t[i+1]>0)) printf("+: %i ",i);
        }

    }


}


void main() {



   char *commandset=(char *) malloc (255);   //command string separated by komma
   //char *token=(char *) malloc (255);
   //char *cp=(char *) malloc (255);
   unsigned long LocalIbsta;
   char SpollByte;

   time_t t;
   int i,j;

   /* Intializes random number generator */
   srand((unsigned) time(&t));

   //for (i=0;i<1000;i++) {printf("%0.5f ",frand());}


   //writef_trace("c:\\werkstatt\\pn\\testtrace.bnoise");

   //tracedata[11][1007]=1;
   //tracedata[12][1007]=1;
   //tracedata[13][1007]=1;

   //writef_tracetxt("c:\\werkstatt\\pn\\testtrace.pdat");



/*****************************************************************************
 * Initialization - Done only once at the beginning of your application.
 *****************************************************************************/

   Device35601 = ibdev(                /* Create a unit descriptor handle         */
         BoardIndex,              /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
         PrimaryAddress35601,          /* Device primary address                  */
         SecondaryAddress35601,        /* Device secondary address                */
         T10s,                    /* Timeout setting (T10s = 10 seconds)     */
         1,                       /* Assert EOI line at end of write         */
         0);                      /* EOS termination mode                    */
   if (Ibsta() & ERR) {           /* Check for GPIB Error                    */
      GpibError("ibdev Error");
   }

   ibclr(Device35601);                 /* Clear the device                        */
   if (Ibsta() & ERR) {
      GpibError("ibclr Error");
   }

   Device3585 = ibdev(                /* Create a unit descriptor handle         */
         BoardIndex,              /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
         PrimaryAddress3585,          /* Device primary address                  */
         SecondaryAddress3585,        /* Device secondary address                */
         T10s,                    /* Timeout setting (T10s = 10 seconds)     */
         1,                       /* Assert EOI line at end of write         */
         0);                      /* EOS termination mode                    */

   if (Ibsta() & ERR) {           /* Check for GPIB Error                    */
      GpibError("ibdev Error");
   }
   ibclr(Device3585);                 /* Clear the device                        */
   if (Ibsta() & ERR) {
      GpibError("ibclr Error");
   }

    Device3562 = ibdev(                /* Create a unit descriptor handle         */
         BoardIndex,              /* Board Index (GPIB0 = 0, GPIB1 = 1, ...) */
         PrimaryAddress3562,          /* Device primary address                  */
         SecondaryAddress3562,        /* Device secondary address                */
         T10s,                    /* Timeout setting (T10s = 10 seconds)     */
         1,                       /* Assert EOI line at end of write         */
         0);                      /* EOS termination mode                    */

   if (Ibsta() & ERR) {           /* Check for GPIB Error                    */
      GpibError("ibdev Error");
   }
   ibclr(Device3562);                 /* Clear the device                        */
   if (Ibsta() & ERR) {
      GpibError("ibclr Error");
   }


/*
   range_3562=7;

   i3562_pwrspec_init();

   i3562_pwrspec(10,range_3562,4);

   i3562_pwrspec(10,range_3562,4);

   getchar();
   exit(1);
*/
   //i3562_timeb();



   toggle_i(NOCOMMAND); //make sure the GPIB is working with 35601a interface
   toggle_i(OVERLOAD);

   // commandset= "-K6,-K7,-K1,-K13,K8,K9,-K11,K12,K10,S3,-S4";

 //  commandset= "-K1,-K13,K8,K9,K11,K12,K10,S3,-S4"; //40 db gain

   //commandset= "K6,K7,S2,-K1,-K13,K8,K9,-K11,K12,K10,S3,-S4"; //tracking gen

  // commandset= "-K6,-K7,-K1,-K13,K8,K9,-K11,K12,-K10,-S1,-S2,-S3,-S4";//loop open



   //printf("%f\n",DROUND(22423432.3434234,9));


   //Cal();

   //printf("PRESS ANY KEY!\n");
   //getchar();



   zerolatch();


/*    setup_i("K1,K8,K9,K11,S7,L1,L3,L5,L8,L9,K12,-K10,-S3,-S4");

    setup_i("F1");
    toggle_i(TOGGLEACDC);
    getchar();
    setup_i("F2");
    toggle_i(TOGGLEACDC);
    getchar();
    setup_i("F0");
    toggle_i(TOGGLEACDC);
    getchar();



    getchar();
exit(1);

*/
   Gain1=6.0;
   Gain2=6.0;
   Amplifier=0;



   getuserparms();

  //readf_cal("c:\\werkstatt\\pn\\testcal.cal"); //need to watch out for atten1 values etc


   value_i(DAC,0.00);//0.1
   value_i(GAIN1,Gain1);//6
   value_i(GAIN2,Gain2);//20
   value_i(LEADLAG,0);//2
   value_i(ATTEN1,Atten1db);//0
   value_i(ATTEN2,Atten2db);//0

   setup_i("K12,K10,S3,S8,L1,L3,L5,L8,L9,S4"); //close loop


//printf("...\n\n");
//getchar();

   Measuretype_t=0; //phase noise measurement
   Caltype_t=2; //beatnote measurement of constant

   setup_i("L1,L3,L5,L8,L9,K12,-K10,-S3,-S4"); //loop is open


   if (Mixerfreq<9.5E+7) {setup_i("K8,K9"); printf("2 MHz LPF is IN\n");}      // ! 2MHz LPF
   if (Mixerfreq>=9.5E+7) {setup_i("-K8,-K9"); printf("2 MHz LPF is OUT\n");}   //LFP out

   if (Mixer==1) {setup_i("-K13");}
   if (Mixer==2) {setup_i("K13");}
   if (Mixer<3) {setup_i("-K1");} //internal mixers
   if (Mixer==3) {setup_i("K1");} //External mixer

   print_i_setup();



   //printf("%f\n",FNPround(21172.213143213,-4));


   readf_cal("c:\\werkstatt\\pn\\testcal.cal");

   Approxfreq=28800e3;

   autorange85();



  getvcoslope();

  Getphaseslope(Vbeatnote,Fbeatnote,Measuretype_t,Caltype_t);

  // writef_cal("c:\\werkstatt\\pn\\testcal.cal");


 // readf_cal("c:\\werkstatt\\pn\\testcal.cal");

 //  printf("Press key...\n");
 //  getchar();

   Charloop();

  // printf("Press key to start PN measurement...\n");
  // getchar();

   printf("Setting up for PN measurement...\n");
 //  print_i_setup();

   zerolatch();

   setup_i("K12,K10,S3,S8,L1,L3,L5,L8,L9,S4"); //close loop

   value_i(DAC,Lockvoltage);//0.1

   value_i(GAIN1,Gain1);//6
   value_i(GAIN2,Gain2);//20


   value_i(LEADLAG,Laglead);//2
   value_i(ATTEN1,Atten1db);//0
   value_i(ATTEN2,Atten2db);//0
 //  print_i_setup();

 //  printf("lead and atten is set...\n");
 //  getchar();




   setup_i("K12,K10,S3,S8,L1,L3,L5,L8,L9,S4"); //close loop

   //printf("close sent\n");
   //printf("Ampl %i\n",Amplifier);
   //getchar();

   Amplifier=1;

   if (Amplifier==1) {setup_i("K11");} else  {setup_i("-K11");}
   if (Amplifier==0) { setup_i("S8");}
   if (Amplifier==1) { setup_i("S7");} //route the correct signal to the LF board

   if (Mixerfreq<9.5E+7) {setup_i("K8,K9"); printf("2 MHz LPF is IN\n");}      // ! 2MHz LPF
   if (Mixerfreq>=9.5E+7) {setup_i("-K8,-K9"); printf("2 MHz LPF is OUT\n");}   //LFP out

   if (Mixer==1) {setup_i("-K13");}
   if (Mixer==2) {setup_i("K13");}
   if (Mixer<3) {setup_i("-K1");} //internal mixers
   if (Mixer==3) {setup_i("K1");} //External mixer


   //value_i(DAC,Lockvoltage);//set DAC for lock voltage
  // printf("DAC set at: %0.3f Volt\n",Lockvoltage);
 //  print_i_setup();

   commandset= "-K6,-K7,K12,K10,-S1,-S2,S3,S4";//loop closed

   setup_i(commandset);
   wait_s01(20);
   toggle_i(OUTOFLOCK);

   //printf("Press key to start PN measurement...\n");
   //getchar();

   printf("Start PN measurement...\n");

   printf("Running getdata...\n");
   getdata();


   //** need to add autorange after each filter change
   range_3562=7;

   i3562_pwrspec_init();

   setup_i("F0");  //seg 3: F2; seg 4-6 F1, seg 7- F0;
   toggle_i(TOGGLEACDC);
   i3562_pwrspec(10,range_3562,30);

   i3562_pwrspec(9,range_3562,30);

   i3562_pwrspec(8,range_3562,30);

   i3562_pwrspec(7,range_3562,30);

   setup_i("F1");  //seg 3: F2; seg 4-6 F1, seg 7- F0;
   toggle_i(TOGGLEACDC);

   i3562_pwrspec(6,range_3562,5); //5

   i3562_pwrspec(5,range_3562,4); //4
/*
   i3562_pwrspec(4,range_3562,3); //3


   setup_i("F2");  //seg 3: F2; seg 4-6 F1, seg 7- F0;
   toggle_i(TOGGLEACDC);

   i3562_pwrspec(3,range_3562,2); //3
*/

   setup_i("F0");  //seg 3: F2; seg 4-6 F1, seg 7- F0;
   toggle_i(TOGGLEACDC);


   do_trace_corr();


   writef_tracetxt("c:\\werkstatt\\pn\\test10e amp 5khz 8645a 288000.pnd");


/*****************************************************************************
 * Uninitialization - Done only once at the end of your application.
 *****************************************************************************/

   ibonl(Device35601, 0);              /* Take the device offline                 */
   if (Ibsta() & ERR) {
      GpibError("ibonl Error");
   }

   ibonl(Device3585, 0);              /* Take the device offline                 */
   if (Ibsta() & ERR) {
      GpibError("ibonl Error");
   }

   exit(0);

}


/*****************************************************************************
 *                      Function GPIBERROR
 * This function will notify you that a NI-488 function failed by
 * printing an error message.  The status variable IBSTA will also be
 * printed in hexadecimal along with the mnemonic meaning of the bit
 * position. The status variable IBERR will be printed in decimal
 * along with the mnemonic meaning of the decimal value.  The status
 * variable IBCNT will be printed in decimal.
 *
 * The NI-488 function IBONL is called to disable the hardware and
 * software.
 *
 * The EXIT function will terminate this program.
 *****************************************************************************/
void GpibError(const char *msg) {

    printf("%s\n", msg);

    printf("Ibsta() = 0x%x  <", Ibsta());
    if (Ibsta() & ERR )  printf(" ERR");
    if (Ibsta() & TIMO)  printf(" TIMO");
    if (Ibsta() & END )  printf(" END");
    if (Ibsta() & SRQI)  printf(" SRQI");
    if (Ibsta() & RQS )  printf(" RQS");
    if (Ibsta() & CMPL)  printf(" CMPL");
    if (Ibsta() & LOK )  printf(" LOK");
    if (Ibsta() & REM )  printf(" REM");
    if (Ibsta() & CIC )  printf(" CIC");
    if (Ibsta() & ATN )  printf(" ATN");
    if (Ibsta() & TACS)  printf(" TACS");
    if (Ibsta() & LACS)  printf(" LACS");
    if (Ibsta() & DTAS)  printf(" DTAS");
    if (Ibsta() & DCAS)  printf(" DCAS");
    printf (" >\n");

    printf ("Iberr() = %d", Iberr());
    if (Iberr() == EDVR) printf(" EDVR <Driver error>\n");
    if (Iberr() == ECIC) printf(" ECIC <Not Controller-In-Charge>\n");
    if (Iberr() == ENOL) printf(" ENOL <No Listener>\n");
    if (Iberr() == EADR) printf(" EADR <Address error>\n");
    if (Iberr() == EARG) printf(" EARG <Invalid argument>\n");
    if (Iberr() == ESAC) printf(" ESAC <Not System Controller>\n");
    if (Iberr() == EABO) printf(" EABO <Operation aborted>\n");
    if (Iberr() == ENEB) printf(" ENEB <No GPIB board>\n");
    if (Iberr() == EOIP) printf(" EOIP <Async I/O in progress>\n");
    if (Iberr() == ECAP) printf(" ECAP <No capability>\n");
    if (Iberr() == EFSO) printf(" EFSO <File system error>\n");
    if (Iberr() == EBUS) printf(" EBUS <Command error>\n");
    if (Iberr() == ESTB) printf(" ESTB <Status byte lost>\n");
    if (Iberr() == ESRQ) printf(" ESRQ <SRQ stuck on>\n");
    if (Iberr() == ETAB) printf(" ETAB <Table Overflow>\n");
    if (Iberr() == ELCK) printf(" ELCK <Lock error>\n");
    if (Iberr() == EARM) printf(" EARM <Ibnotify rearm error>\n");
    if (Iberr() == EHDL) printf(" EHDL <Invalid Handle>\n");
    if (Iberr() == EWIP) printf(" EWIP <Wait already in progress>\n");
    if (Iberr() == ERST) printf(" ERST <Notification cancelled due to reset>\n");
    if (Iberr() == EPWR) printf(" EPWR <Power error>\n");

    printf("Ibcnt() = %u\n", Ibcnt());
    printf("\n");

    /* Call ibonl to take the device and interface offline */
    //ibonl(Device, 0);

    exit(1);
}
