/*
   This programm is used to set the auger spectrometer to a single
   electron energy and monitor the Intensity of this line.
   optionally a second energy may be specified.
*/

#define ECALTMP "ecal.auger"

#ifdef UNIX
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/hpibio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#endif

#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <spec.h>
#include <auxcfg.h>

#define SETUPFILE "auger.set"

float x,y,*spc,*err,*tim;
int   fdlockin, delay, ntimes;
float stepv, startv, stopv, old_voltage;
float ecal, delta_u;
int spcmax;
char *cname[110];
char *lname[110];
float *Eauger, *Ebind, *sens, *Ratom;
int spc_ptr;
int min_max;

help()
{
printf("This program monitors one (or two) auger electron energy lines\n");
printf("monaug [options]\n");
printf("possible options:\n");
printf("  -rs         read setup (to %s)\n",SETUPFILE);
printf("  -us         use setup (restore from %s)\n",SETUPFILE);
printf("  -scan       scan one spectrum and store result to stdout\n");
printf("              use option -o to redirect output to a file\n");
printf("  -add spcfile  read old spectrum and append new data\n");
printf("  -o spcfile  redirect output spectrum to file\n");
printf("  -min        take minimum instead of (max -min)\n");
printf("  -max        take maximum instead of (max -min)\n");
printf("  -delay n    use n ms delay Default is %d\n",delay);
printf("  -times n    make n measurements. Default is %d\n",ntimes);
printf("  -u  n.m     specify spectrometer voltage [V]\n");
printf("  -u1 n.m     specify spectrometer voltage [V]\n");
printf("  -u2 n.m     specify alternate voltage [V]\n");
printf("  -du n.m     deviation from spectrometervoltage [V], default is %f\n",delta_u);
printf("  -e  n.m     specify electron enery for Spectrometer [eV]\n");
printf("  -e1 n.m     specify electron enery for Spectrometer [eV]\n");
printf("  -e2 n.m     alternate electron enery for Spectrometer [eV]\n");
printf("  -n  n.m     specify element name instead of energy\n");
printf("  -n1 n.m     specify element name instead of energy\n");
printf("  -n2 n.m     specify alternate element name\n");
printf("  -v          means verbouse, for debugging purposes\n");
printf("  -comment str   set comment\n");
printf("  -notim      do not append time to comment\n");
printf("if there is a file >%s<, this is taken for energy calibration\n",ECALTMP);
printf("see also Aux_Config :auger\n\n");
}


float find_energy(z)
char *z;
{
int i,n,m;

   z[0] = z[0] & 223;               /* = toupper ! */
   if(z[1] > 0) z[1] = z[1] | 32;   /* = tolower ! */
   for(n = 0; n < 110; n++) {
      if(strcmp(cname[n],z) == 0) break;
   }
   if(n >= 109) {
      printf("sorry, element >%s< not found\n");
      exit(0);
   }
   return(Eauger[n]);
}

main(argc,argv)
int argc;
char *argv[];
{
int i,n,m;
time_t izeit;
char c,s[80],zeit[80];
FILE *fp;
char *z,*comment, *elements;
int channel;
int flag_v;
float energy;
float v1, v2;
float real_t,real_y;
struct tm *now;

   fdlockin = auxopen("auger");
   delay = atoi(auxparams[4]);
   ntimes = 3;
   stepv = atosf(auxparams[5]);
   delta_u = 5 * stepv;
   ecal = atosf(auxparams[8]);

   spc_ptr = 0;
   min_max = 0;

   if(argc < 2) {
      help();
      close(fdlockin);
      exit(0);
   }

   fp = fopen(ECALTMP,"r");
   if(fp != NULL) {
      fgets(s,80,fp);
      ecal = atosf(s);
      fclose(fp);
   }
   Eauger = (float *) calloc(110,sizeof(float));
   Ebind = (float *) calloc(110,sizeof(float));
   sens = (float *) calloc(110,sizeof(float));
   Ratom = (float *) calloc(110,sizeof(float));
   z = (char *) malloc(80);
   comment = (char *) malloc(80);
   elements = (char *) malloc(80); strcpy(elements,"elements");
   spc= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
   err= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
   tim= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
   if(tim==NULL) {
      printf("sorry, not enough memory\n");
      exit(-1);
   }
   for(n = 0; n < 110; n++) {
      cname[n] = (char *) malloc(4); cname[n][0] = 0;
      lname[n] = (char *) malloc(16); lname[n][0] = 0;
      sens[n] = 0.0;
      Eauger[n] = 0.0;
      Ebind[n] = 0.0;
      Ratom[n] = 0.0;
   }

   if(checkopt(argc,argv,"-rs",s)) read_setup(SETUPFILE);
   if(checkopt(argc,argv,"-us",s)) use_setup(SETUPFILE);
   if(checkopt(argc,argv,"-add",s)) {
      spc_ptr = readspec(s,spc,err,tim,z);
      strcpy(_spc_onam,s);
   }
   if(checkopt(argc,argv,"-min",s)) min_max = 1;
   if(checkopt(argc,argv,"-max",s)) min_max = 2;
   if(checkopt(argc,argv,"-delay",s)) delay = atoi(s);
   if(checkopt(argc,argv,"-times",s)) ntimes = atoi(s);
   if(checkopt(argc,argv,"-cal",s))  ecal = atosf(s);
   _tica = ecal * stepv;
   strcpy(comment,"auger spectrum");
   if(checkopt(argc,argv,"-comment",s)) strcpy(comment,s);
   v1 = -1.0; v2 = -1.0;
   if(checkopt(argc,argv,"-u",s)) v1 = atosf(s);
   if(checkopt(argc,argv,"-u1",s)) v1= atosf(s);
   if(checkopt(argc,argv,"-u2",s)) v2= atosf(s);
   if(checkopt(argc,argv,"-du",s)) delta_u= atosf(s);
   if(checkopt(argc,argv,"-e",s)) {
      energy = atosf(s);
      v1 = energy / ecal;
   }
   if(checkopt(argc,argv,"-e1",s)) {
      energy = atosf(s);
      v1 = energy / ecal;
   }
   if(checkopt(argc,argv,"-e2",s)) {
      energy = atosf(s);
      v2 = energy / ecal;
   }
   if(checkopt(argc,argv,"-n",s)) {
      read_elements(elements);
      energy = find_energy(s);
      v1 = energy / ecal;
   }
   if(checkopt(argc,argv,"-n1",s)) {
      read_elements(elements);
      energy = find_energy(s);
      v1 = energy / ecal;
   }
   if(checkopt(argc,argv,"-n2",s)) {
      read_elements(elements);
      energy = find_energy(s);
      v2 = energy / ecal;
   }

   if(v1 < 0.0) {
      printf("you MUST specify at least one spectrometer voltage\n");
      exit(0);
   }

   izeit=time(NULL);                        /* get actual time */
   now=localtime(&izeit);
   strftime(zeit,20,"   %H:%M %d.%m.%y",now);
   if(!checkopt(argc,argv,"-notim",s)) strcat(comment,zeit);
   if(checkopt(argc,argv,"-v",s)) {
      printf("v1 = %f\nv2 = %f\n",v1,v2);
   }

   if(checkopt(argc,argv,"-scan",s)) {
      scan(spc,err,v1,v2);
      writespec("",spc,err,spc_ptr,2,comment);
      if(_spc_onam[0] != 0) {
         strcpy(s,_spc_onam); strcat(s,".tim");
         writespec(s,tim,err,n,2,comment);
      }
   }
   free(tim); free(err); free(spc);
   free(elements); free(comment); free(z);
   for(n = 0; n < 110; n++) {
      free(lname[n]);
      free(cname[n]);
   }
   free(Ratom); free(sens); free(Ebind); free(Eauger);
   close(fdlockin);
   return(0);
}


lockin_out(str)
char str[];
{
char s[80];

   strcpy(s,str);
   strcat(s,"\n");
   write(fdlockin,s,strlen(s));
}

lockin_in(str)
char str[];
{
char c;
int n,err;

   c = 0; n = 0;
   while(c != 10) {
      err = read(fdlockin,&c,1);
      if(err != 1) {
         fprintf(stderr,"auger / lockin_in : error while reading lock in\n");
         str[n] = 0;
         return(n);
      }
      str[n++] = c;
   }
   str[n] = 0;
   return(n);
}


dummy()
{
}

waitms(milisec)
int milisec;
{

#ifdef AMIGA

int n;

   n = (50 * milisec) / 1000;
   Delay(n);
#endif

#ifdef UNIX

int sec,musec;
struct itimerval rttimer;
struct itimerval old_rttimer;

   signal(SIGALRM,dummy);
   sec = milisec / 1000 ;
   musec = 1000 * (milisec - (1000 * sec));
   rttimer.it_value.tv_sec = sec;
   rttimer.it_value.tv_usec = musec;
   rttimer.it_interval.tv_sec = 0 ;
   rttimer.it_interval.tv_usec = 0 ;
   setitimer(ITIMER_REAL,&rttimer,&old_rttimer);
   pause();
#endif
}
  
read_setup(fname)
char fname[];
{
char s[80];
FILE *fp;

   fp = fopen(fname,"w");

   lockin_out("G");           /* read gain */
   lockin_in(s);
   printf("gain: %s",s);
   fprintf(fp,"%s",s);

   lockin_out("F");           /* read frequency */
   lockin_in(s);
   printf("frequency: %s",s);
   fprintf(fp,"%s",s);

   lockin_out("T 1");           /* read time constant */
   lockin_in(s);
   printf("time constant: %s",s);
   fprintf(fp,"%s",s);

   lockin_out("P");           /* read phase */
   lockin_in(s);
   printf("phase: %s",s);
   fprintf(fp,"%s",s);

   fclose(fp);
}

use_setup(fname)
char fname[];
{
char z[80], s[80];
FILE *fp;

   fp = fopen(fname,"r");

   fgets(s,80,fp);               /* Gain */
   sprintf(z,"G %s",s);
   lockin_out(z);

   fgets(s,80,fp);               /* frequency */
   sprintf(z,"F %s",s);
/*   lockin_out(z);    READ ONLY ! */

   fgets(s,80,fp);               /* time constant */
   sprintf(z,"T 1,%s",s);
   lockin_out(z);

   fgets(s,80,fp);               /* phase */
   sprintf(z,"P %s",s);
   lockin_out(z);

   fclose(fp);
}

float read_aes(u)
float u;
{
float x, actv, stepv;
int i,n;
char s[80];

   x = u - old_voltage;
   stepv = 0.2; if(x < 0.0) stepv = -0.2;
   actv = old_voltage;
   n = x / stepv;
   
   sprintf(s,"X 6,%f\n",u);
   lockin_out(s);
   old_voltage = u;
   waitms(delay);
   lockin_out("Q");
   lockin_in(s);
   x = atosf(s);
   waitms(delay);
   lockin_out("Q");
   lockin_in(s);
   x = x + atosf(s);
   waitms(delay);
   lockin_out("Q");
   lockin_in(s);
   x = x + atosf(s);
   return(x / 3.0);
}

float read_diff_aes(v)
float v;
{
float actv,y,maxy,miny;
int i,n,m;

   actv = v - delta_u;
   i = 0; maxy = -1.0E10; miny = 1.0E10;
   y = read_aes(actv);
   waitms(2000);
   while(actv < (v + delta_u)) {
      y = read_aes(actv);
      if(y > maxy) maxy = y;
      if(y < miny) miny = y;
      actv = actv + stepv;
   }
   printf("max = %f , min = %f\n",maxy,miny);
   switch(min_max) {
      case 0: return(maxy - miny); break;
      case 1: return(miny); break;
      case 2: return(maxy); break;
   }
}

scan(spc,err,v1,v2)
float spc[], err[];
float v1, v2;
{
int i,n;
float x;
char s[80];

   old_voltage = 0.0;
   for(n = 0; n <= ntimes; n++) {
      x = read_diff_aes(v1);
      spc[n+spc_ptr] = x;
      err[n+spc_ptr] = 0.0;
      tim[n+spc_ptr] = n + spc_ptr;
      printf("dv1=%f V    --- aes=%f\n",v1,x);
      if(v2 > 0.0) {
         n = n + 1;
         x = read_diff_aes(v2);
         spc[n+spc_ptr] = x;
         err[n+spc_ptr] = 0.0;
         tim[n+spc_ptr] = n + spc_ptr - 1;
         printf("dv2=%f V    --- aes=%f\n",v2,x);
      }
   }
   spc_ptr = n + spc_ptr;
   return(spc_ptr);
}

read_elements(elements)
char *elements;
{
int i,n,m;
char z[80];
FILE *fp;

   fp = fopen(elements,"r");
   if(fp == NULL) {
      fprintf(stderr,"file >%s< not found !\n",elements);
      exit(0);
   }
   while(!feof(fp)) {
      fgets2(z,80,fp);
      if(feof(fp)) break;
      if(z[0] == ';') continue;
      if(z[0] < 33) continue;
      n = atoi(z);
      if((n < 1) || (n > 108)) {
         fprintf(stderr,"error in >%s< unexpected >%s<\n",elements,z);
         exit(0);
      }
      fgets2(z,80,fp); strcpy(cname[n],z);
      fgets2(z,80,fp); strcpy(lname[n],z);
      fgets2(z,80,fp); sens[n] = atosf(z);
      fgets2(z,80,fp); Eauger[n] = atosf(z);
      fgets2(z,80,fp); Ebind[n] = atosf(z);
      fgets2(z,80,fp); Ratom[n] = atosf(z);
   }
   fclose(fp);
}

fgets2(s,n,fp)
char *s;
int n;
FILE *fp;
{
int i,l;

   fgets(s,n,fp);
   l = strlen(s);
   for(i = 0; i <= l; i++) {
      if(s[i] < 33) s[i] = 0;
      if(s[i] == ';') s[i] = 0;
   }
}

