/*
   This Program scans one spectrum from the Auger Spectrometer
   and stores it as LISE spectrum (in binary Real format).
*/

#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"

int   fdlockin, delay, sweep, ntimes;
float stepv, startv, stopv;
float ecal;
float *spc, *err, *tim;
char comment[80];
time_t StartTime, ActTime, LastUpdate;
int update_intervall;
char  *MacroName, *TempSpec;

help()
{
printf("This program is used to communicate with the Auger Spectrometer\n");
printf("via the SR510 Lock in amplifier\n");
printf("auger [options]\n");
printf("possible options:\n");
printf("  -rs         read setup (to %s)\n",SETUPFILE);
printf("  -us         use setup (restore from %s)\n",SETUPFILE);
printf("  -x5 n.m     frequency calibration\n");
printf("  -scan       scan one spectrum and store result to stdout\n");
printf("              use option -o to redirect output to a file\n");
printf("  -delay n    use n ms delay between steps. Default is %d\n",delay);
printf("  -sweep n    sweeps n times and accumulate spectra\n");
printf("  -times n    reads LockIn output n times. Default is %d\n",ntimes);
printf("  -step n.m   stepwith n.m V  Default is %f\n",stepv);
printf("  -start n.m  start voltage [V]  Default is %f\n",startv);
printf("  -estart n.m start energy [eV]\n");
printf("  -stop n.m   stop voltage [V]  Default is %f\n",stopv);
printf("  -estop n.m  end energy [eV]\n");
printf("  -cal n.m    calibration factor in eV/V Default is %f\n",ecal);
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");
}

main(argc,argv)
int argc;
char *argv[];
{
int i,n,m;
char c,s[80],z[80],zeit[80];
FILE *fp;
struct tm *now;

   MacroName = (char *) malloc(80);
   TempSpec = (char *) malloc(80);

   fdlockin = auxopen("auger");
   delay = atoi(auxparams[4]);
   stepv = atosf(auxparams[5]);
   startv = atosf(auxparams[6]);
   stopv = atosf(auxparams[7]);
   ecal = atosf(auxparams[8]);
   ntimes = atoi(auxparams[9]);
   update_intervall = atoi(auxparams[10]); /* update intervall for gfx */
   strcpy(TempSpec,auxparams[11]);         /* temporary spectrum name */
   strcpy(MacroName,auxparams[12]);        /* Macro to call for gfx */
   sweep = 1;

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

   fp = fopen(ECALTMP,"r");
   if(fp != NULL) {
      fgets(s,80,fp);
      ecal = atosf(s);
      fclose(fp);
   }

   if(checkopt(argc,argv,"-rs",s)) read_setup(SETUPFILE);
   if(checkopt(argc,argv,"-us",s)) use_setup(SETUPFILE);
   if(checkopt(argc,argv,"-x5",s)) {
      sprintf(z,"X5,%s",s);
      lockin_out(z);
   }
   if(checkopt(argc,argv,"-delay",s)) delay = atoi(s);
   if(checkopt(argc,argv,"-sweep",s)) sweep = atoi(s);
   if(checkopt(argc,argv,"-times",s)) ntimes = atoi(s);
   if(checkopt(argc,argv,"-step",s)) stepv = atosf(s);
   if(checkopt(argc,argv,"-start",s)) startv = atosf(s);
   if(checkopt(argc,argv,"-stop",s)) stopv = atosf(s);
   if(checkopt(argc,argv,"-cal",s))  ecal = atosf(s);
   _tica = ecal * stepv;
   if(checkopt(argc,argv,"-estart",s)) startv = atosf(s) / ecal;
   if(checkopt(argc,argv,"-estop",s)) stopv = atosf(s) / ecal;
   strcpy(comment,"auger spectrum");
   if(checkopt(argc,argv,"-comment",s)) strcpy(comment,s);

   StartTime = time(NULL);             /* get actual time */
   ActTime = StartTime;
   LastUpdate = StartTime;
   now=localtime(&ActTime);
   strftime(zeit,20,"   %H:%M %d.%m.%y",now);
   if(!checkopt(argc,argv,"-notim",s)) strcat(comment,zeit);

   if(checkopt(argc,argv,"-scan",s)) {
      spc= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
      err= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
      tim= (float *)calloc(_MAXSPCLEN+2,sizeof(float));
      n = scan(spc,err);
      writespec("",spc,err,n,2,comment);
      if(_spc_onam[0] != 0) {
         strcpy(s,_spc_onam); strcat(s,".tim");
         writespec(s,tim,err,n,2,comment);
      }
   }
   free(MacroName); free(TempSpec);
   free(tim); free(err); free(spc);
   close(fdlockin);
}

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);

   lockin_out("X5");           /* read X5 */
   lockin_in(s);
   printf("X5: %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);

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

   fclose(fp);
}


scan(spc,err)
float spc[], err[];
{
float actv,x;
int i,n,m,dir;
char s[80], z[80];

   dir = 1; n = 0; m=0;
   LastUpdate = time(NULL);
   sprintf(s,"X6,%f\n",startv);
   for(i = 0; i < _MAXSPCLEN; i++) spc[i] = 0;
   sleep(2);
   lockin_out(s);
   for(i = 0; i < sweep; i++) {
      do {
         actv = startv + (n * stepv);
         sprintf(s,"X6,%f\n",actv);
         lockin_out(s);
         waitms(delay); x = 0;
         for(m = 0; m < ntimes; m++) {
            lockin_out("Q");
            lockin_in(s); x = x + atosf(s);
         }
         spc[n] = spc[n] + (x / ntimes);
         tim[n] = ecal * actv;
         err[n] = 0.0;      /* Who knows how to calculate the error ? */
         if(n > m) m = n;
         n = n + dir;
         /* now look, if we have to call the external gfx macro */
         ActTime = time(NULL);
         if(((int)difftime(ActTime,LastUpdate) > update_intervall)
             || (actv ==stopv)) {
            LastUpdate = ActTime;
            strcpy(z,_spc_onam); _spc_onam[0]=0; /* prevent name overriding */
            writespec(TempSpec,spc,err,m,2,comment);
            strcpy(_spc_onam,z);
            strcpy(z,TempSpec); strcat(z,".tim");
            writespec(z,tim,err,m,2,comment);
            sprintf(z,"(/bin/sh %s %s)&",MacroName,TempSpec);
            system(z); sleep(1);
         }
         /* continue with scanning */
      } while((actv <= stopv) && (actv >= startv));
      dir = -1 * dir; n = n + (2 * dir);
   }
   lockin_out("X6,0.0\n");
   return(m);
}

