#include "tktds2x0.h"
#include "collisions4.h"
#include <NIDAQmx.h>
#include <easyio.h>
#include <gpib.h>
#include <analysis.h>
#include <dataacq.h>
#include "asynctmr.h"
#include <formatio.h>
#include <ansi_c.h>
#include <utility.h>                                                  
#include <userint.h>
#define numtemps  4

//#define N 2500
static char writebuffer[30];
static int plothandle, plothandle2;  
	int time_base = 500;
	int scale = 5;
	int yzero = 0;

	
// data structure for queues 
int acqcmdTSQ, acqdataTSQ;
static int acqThreadFlush;

  
#define SMMACQCMD struct t_smmacqcmd
SMMACQCMD { int onoff, time, type, smooth, numav, frequency, egy, intensity, temperature, Q300, QT, numvolts;};

#define SMMACQDATA struct t_tsmmacq
SMMACQDATA { int num; double  *scope, absorption, concentration, pressure;};

SMMACQCMD acq; 
SMMACQDATA acqdata;
SMMACQDATA aqrd;

int acqthread(void *dumy);
static int acqThreadID; 

/* function prototypes */
void CVICALLBACK acqCallback(int qHandle, unsigned int event, int value, void *callbackData);
void CVICALLBACK Change_Lines(int menuBarHandle, int menuItemID, void *callbackData, int panelHandle);
void loadlog(void);
void loadcat(char *catpath);
double ZWOF(double x, double *a, int npar);
int zwofz(double w[], double z[]);

/* GPIB basics */
int Init_Device(char *str, int len);
int Close_Device(int device);
int Write_Device(int device, char *str, int len);

/* global data */
static int stripchart, PMAINP, PTEMPLOG, lakeshore, anritsu, sr844, tds210, timer, amfm, wave, go, autoscale, trace, smoothie;
double pi, d, df, frequency, power, modfreq, modamp, amrate, period, factor, currenttemperature, path;
long fundamental;
int harmonic;
void scalefrequency(void);
void initScope(void);
void InitDAQ(void);
//int    acqcmdTSQ, acqdataTSQ;
static double lasttemps[numtemps], interval, dt[4][5];

void dimension_arrays(int catnum, int n);
int N=2500;
static double  *x, *frequencies, *zero, *bkg, *shiftzero, *shiftbkg, *scope, *shiftscope;
static char  *readscope; 
static double p1, p2, p3, p4, p5;

//for catalogs
static char lastcat[260], catpath[260];
static int   menubarhandle, catnum, catnow;
FILE* cathandle;
double fcatfreq, fcatint, fcategy;

//New DAQ stuff
TaskHandle  DAQHandle=0, DAQInputs=0, DAQClock=0, DAQTrig=0; 
float64     DAQdata[2], *voltages; 
int N, gain[8];

void main ()
{
int i;
char buffer[300];
  PMAINP  = LoadPanel (0, "collisions4.uir", MainP);
  PTEMPLOG = LoadPanel (0, "collisions4.uir", TEMPLOG);
  menubarhandle = LoadMenuBar(PMAINP, "collisions4.uir", MENUBAR);

  DisplayPanel (PMAINP);
  SetActivePanel (PMAINP);
  SetCtrlAttribute (PMAINP, MainP_Start_SCOPE, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
  GetCtrlVal(PMAINP, MainP_NUMPOINTS, &N);
  GetDir(buffer);
  interval = 10.0;
  catnow = 1;
  loadcat(strcat(buffer, "\\300_GHz.cat"));
  dimension_arrays(catnum, N);
  Change_Lines (menubarhandle, 396, 0, PMAINP);
  if (!lakeshore) lakeshore = Init_Device("LS218S", 6);
  //if (!anritsu) anritsu = Init_Device("ANRITSU", 6);
  if (!sr844) sr844 = Init_Device("LIA", 5);
//  if (!tds210) tds210 = Init_Device("SCOPE", 5);
  if (anritsu) Change_Frequency (PMAINP, MainP_FREQUENCY, 1, NULL, NULL, NULL);
  if (tds210) initScope();		

  
  //DAQmxCreateTask ("", &DAQHandle);
  DAQmxCreateTask ("", &DAQInputs);
  InitDAQ(); 
  
  CmtNewTSQ (10, sizeof(SMMACQCMD), OPT_TSQ_DYNAMIC_SIZE, &acqcmdTSQ);
  CmtNewTSQ (160, sizeof(SMMACQDATA), OPT_TSQ_DYNAMIC_SIZE, &acqdataTSQ);
    
  CmtInstallTSQCallback (acqdataTSQ, EVENT_TSQ_ITEMS_IN_QUEUE, 1, acqCallback, NULL, CmtGetCurrentThreadID(), NULL);
  CmtScheduleThreadPoolFunctionAdv (DEFAULT_THREAD_POOL_HANDLE,   acqthread, NULL,  THREAD_PRIORITY_TIME_CRITICAL, NULL, 0, NULL, 0, &acqThreadID);
  
  d = 0.2819; //Doppler width MHz
  for (i = 0; i < N; ++i) x[i] = i/d;
  pi = acos(-1);
  path = 59.0; //cm
  currenttemperature = 298.0; //Kelvin

  for (i = 0; i < N; ++i) bkg[i] = 1.0;
  RunUserInterface ();
  /* shut down and prepare for exit */
  acq.onoff = 0;
//  CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, acqThreadID, OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
//  CmtDiscardTSQ (acqcmdTSQ); CmtDiscardTSQ  (acqdataTSQ);
  if (tds210) Close_Device(tds210); 
  if (lakeshore) Close_Device(lakeshore);
  if (anritsu) Close_Device(anritsu);
  if (sr844) Close_Device(sr844);
  } /*end main */

void initScope(void)
{
	Write_Device(tds210, "DATa:SOUrce CH2", 15);
	Write_Device(tds210, "TRIGger:MAIn:EDGE:SLOpe FALL", 28);
	Write_Device(tds210, "DATa:ENCdg ASC", 14);//RIBinary", 19);
//	Write_Device(tds210, "CH2:POS 0.0", 11); 
	Change_Scope (PMAINP, MainP_Time, 1, NULL, NULL, NULL);
	Write_Device(tds210, "ACQuire:MODe AVErage", 20); 
	Write_Device(tds210, "ACQuire:STOPAfter SEQuence", 24); 
	Change_Trace (PMAINP, MainP_TRACE, 1, NULL, NULL, NULL);
	Write_Device(tds210, "DATa:WIDth 1", 12);
	Write_Device(tds210, "DATa:STARt 0", 12);
    Fmt (writebuffer, "%s<DATa:STOP %d", N);
	Write_Device(tds210, "TRIGger:MAIn:MODe NORM", 22);
	Write_Device(tds210, writebuffer, NumFmtdBytes());
	Write_Device(tds210, "CH1:POS 0.0", 11); 
	Write_Device(tds210, "CH1:SCA 2.0E0", 13); 
	Change_Auto (PMAINP, MainP_Autoscale, 1, NULL, NULL, NULL);
}

void dimension_arrays(int m, int n)
{
	int k;
	k = m*n;
	frequencies = (double *)malloc(sizeof(double) * k);
	x = (double *)malloc(sizeof(double) * k); 
	bkg = (double *)malloc(sizeof(double) * k);
	scope = (double *)malloc(sizeof(double) * k);
	zero = (double *)malloc(sizeof(double) * n);
	shiftzero = (double *)malloc(sizeof(double) * n);
	shiftbkg = (double *)malloc(sizeof(double) * n);
	readscope = (char *)malloc(sizeof(char) * n);
	shiftscope = (double *)malloc(sizeof(double) * n);

}


int CVICALLBACK Start_Log (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
int i, j;
static int logfilehandle;
FILE *logfile;
static char readbuffer[65], test[216], tempstr[20], tempstr2[20];
static double lsvolts[numtemps], lstemps[numtemps],  dtt;
	switch (event)
	{
		case EVENT_TIMER_TICK:
   			if (lakeshore){
			  if (!logfilehandle) {
				  
				  logfile = fopen ("c:\\My Projects\\collisions.log", "a") ;
   			  	  logfilehandle = 1;
			  }
			  Fmt (writebuffer, "%s<KRDG?");
			  Write_Device(lakeshore, writebuffer, NumFmtdBytes());
			  ibrd (lakeshore, readbuffer, 65);
			  Fmt (tempstr, "%s%d%s", "%", numtemps, "f[x]");
			  Scan (readbuffer, tempstr, lstemps);
			  for (i = 0; i < numtemps; ++i){
				  SetTableCellVal (PMAINP, MainP_TEMPERATURES, MakePoint(1,i+1), lstemps[i]);
			  }
			  
   			  Fmt (writebuffer, "%s<SRDG?");
			  Write_Device(lakeshore, writebuffer, NumFmtdBytes());
			  ibrd(lakeshore, readbuffer, 65);
			  Scan (readbuffer, tempstr, lsvolts);
			  for (i = 0; i < numtemps; ++i){
				  SetTableCellVal (PMAINP, MainP_TEMPERATURES, MakePoint(2,i+1), lsvolts[i]);
				  Fmt (tempstr, "%f[p2]", lstemps[i]);
			      Fmt (tempstr2, "%f[p4]", lsvolts[i]);	 
				  fprintf (logfile, "%s %s ", tempstr, tempstr2);
				  if (stripchart) PlotStripChart (PTEMPLOG, TEMPLOG_STRIPCHART, lstemps, 4, 0, 0, VAL_DOUBLE);
				  for (j = 3; j >= 0; --j) dt[i][j] = dt[i][j+1];
				  dt[i][4] = 60*(lstemps[i] - lasttemps[i])/interval;
				  dtt = (dt[i][0] + dt[i][1] + dt[i][2] + dt[i][3] + dt[i][4])/5.0;
				  SetCtrlVal(PTEMPLOG, TEMPLOG_T1_GAUGE + fmod(i,4), dtt);
				  lasttemps[i] = lstemps[i]; 
			  }	  
			  fprintf (logfile, "\n");
			}
			if (logfilehandle) logfilehandle = fclose(logfile);
			break;
	}
	return 0;
}

/*********** GPIB Calls ***********/
int Init_Device(char *str, int len)
{
	int devicename;
	devicename = OpenDev (str, "");
	ibclr(devicename);
	if (!devicename)  MessagePopup ("GPIB error", "The Device was not found");
	return devicename;
}


int Close_Device (int device)
{
	if (device) device = CloseDev (device);
	return device;
}

  
int Write_Device(int device, char *str, int len)
{
  static int ret;
  if (device <= 0) return ret;
    ret = ibwrt(device, str, len);
    if (ret > 7999) MessagePopup ("WARNING", "Device not responding");
	return ret;
}

/***********END GPIB Calls *************/

int CVICALLBACK Change_Interval (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
int ret;

	GetCtrlVal(PMAINP, MainP_Interval, &interval);
	ret = SetCtrlAttribute (PMAINP, MainP_TIMER, ATTR_INTERVAL, interval);
   return ret;
}	

int CVICALLBACK Pause_Timer (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	   timer = SetCtrlAttribute (PMAINP, MainP_TIMER, ATTR_ENABLED, !timer); 
   return timer;
}

int CVICALLBACK Quit_Interface (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			QuitUserInterface (0);
			break;
	}
	return 0;
}

int CVICALLBACK Change_Frequency (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	static char writebuffer[18];
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(PMAINP, MainP_HARMONIC, &harmonic);
			GetCtrlVal(PMAINP, MainP_FREQUENCY, &frequency);
			GetCtrlVal(PMAINP, MainP_SYNTH_POWER, &power);
			GetCtrlVal(PMAINP, MainP_MOD_FREQUENCY, &modfreq);
			period = 1.0e6/modfreq;  
			GetCtrlVal(PMAINP, MainP_MOD_DEPTH, &modamp);
			GetCtrlVal(PMAINP, MainP_AM_RATE, &amrate); 
			GetCtrlVal(PMAINP, MainP_AMFM, &amfm);
			GetCtrlVal(PMAINP, MainP_Waveform, &wave);
			fundamental = RoundRealToNearestInteger (1000*frequency/harmonic);
			SetCtrlVal(PMAINP, MainP_FUNDAMENTAL, fundamental);
			SetCtrlVal(PMAINP, MainP_FREQUENCY, (double) harmonic*fundamental/1000);
			Fmt (writebuffer, "F1 %dKH", fundamental);
			Write_Device(anritsu, writebuffer, NumFmtdBytes());
			Fmt (writebuffer, "%s<L1 %f[p1]DM", power);
			Write_Device(anritsu, writebuffer, NumFmtdBytes());
			if (amfm == 1) {
				Write_Device(anritsu, "FM9", 3);
				Write_Device(anritsu, "FMV1", 3);
				Write_Device(anritsu, "AM0", 3);
				Fmt (writebuffer,  "%s<FWV%d", wave);
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer,  "%s<FDV %f[p0] KH", (double) modamp/harmonic);
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer, "%s<FMR %f[p0] HZ", modfreq);
                Write_Device(anritsu, writebuffer, NumFmtdBytes());
				//if (tds210) 
				scalefrequency();
			} else if (amfm == 0){
				Write_Device(anritsu, "FM0", 3);
				Write_Device(anritsu, "AM1", 3);
				Write_Device(anritsu, "AM3", 3);
				Write_Device(anritsu, "AM6", 3);
				Write_Device(anritsu, "AMW2", 4);
				Fmt (writebuffer, "%s<ADP1 %f[p1] PCT", modamp); 
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer, "%s<AMR%dHZ", (int) amrate); 
			} else if (amfm == 2){
				Write_Device(anritsu, "FM9", 3);
				Write_Device(anritsu, "FMV1", 3);
				Fmt (writebuffer,  "%s<FWV%d", wave);
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer,  "%s<FDV %f[p0] KH", (double) modamp/harmonic);
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer, "%s<FMR %f[p0] HZ", modfreq);
                Write_Device(anritsu, writebuffer, NumFmtdBytes());
				
				Write_Device(anritsu, "AM7", 3);
				Write_Device(anritsu, "AMW2", 4);
				Fmt (writebuffer, "%s<ADP1 %f[p3] PCT", 100.000); 
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				Fmt (writebuffer, "%s<AMR%dHZ",  (int) amrate); 
				Write_Device(anritsu, writebuffer, NumFmtdBytes());
				//if (tds210)
				scalefrequency();
			}
			Write_Device(anritsu, "RF1", 3);
			break;
	}
	return 0;
}




int CVICALLBACK Go_SCOPE (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
switch (event)
	{
		case EVENT_COMMIT:

		 acq.onoff = !acq.onoff;
		 if (!acq.onoff) {
			 SetCtrlAttribute (PMAINP, MainP_Start_SCOPE, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
			 SetCtrlAttribute (PMAINP, MainP_Start_SCOPE, ATTR_LABEL_TEXT, "Start");
		 } else {
			 SetCtrlAttribute (PMAINP, MainP_Start_SCOPE, ATTR_CMD_BUTTON_COLOR, VAL_RED);
		 	 SetCtrlAttribute (PMAINP, MainP_Start_SCOPE, ATTR_LABEL_TEXT, "Stop");
			 acqdata.num = 0;
		 }
		 CmtWriteTSQData (acqcmdTSQ, &acq, 1, TSQ_INFINITE_TIMEOUT, NULL);

	break;
	}
	return 0;
}

int CVICALLBACK Go_BKG (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{

static int  check, numav, timeout, maxindex, minindex, i,j;
static double max, min;

switch (event)
	{
		case EVENT_COMMIT:
		 go = !go ;
		 if (!go) {
			 SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
			 SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_LABEL_TEXT, "Bkg");
		 } else {
			 SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_CMD_BUTTON_COLOR, VAL_RED);
		 	 SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_LABEL_TEXT, "Bkg Stop");
		     Write_Device(tds210, "ACQ:STATE ON", 12);
			 Write_Device(tds210, "WAIt", 4);
			 Write_Device(tds210, "CURVe?", 6);
	          check = 8001;
	          while (check > 8000) check =ibrd (tds210, readscope, N);
        	  Fmt (writebuffer, "%s<%s%d%s%d%s", "%",N, "d[b1]>%", N,"f");
        	  Scan (readscope, writebuffer, &bkg[catnow*N]);
        	 // LinEv1D (bkg, N, factor, 0.0, bkg);
			  MaxMin1D (&bkg[catnow*N], N, &max, &maxindex, &min, &minindex);
			  for (i = 0; i < N; ++i){
				  if ((i+maxindex) < N) shiftbkg[i] = bkg[catnow*N+i+maxindex];
				  if ((i+maxindex) >= N) shiftbkg[i] = bkg[catnow*N+i+maxindex - (N)];
			  }
			  for (i = 0; i < N; ++i){
				bkg[catnow*N+i] = 0;
				if((i >= smoothie) && (i < N-smoothie)) for (j = -smoothie; j < smoothie+1; ++j) bkg[catnow*N+i] += shiftbkg[i+j];
				bkg[catnow*N+i] /= (double)(2*smoothie+1);
	  			} 
   			  if (plothandle) plothandle = DeleteGraphPlot (PMAINP, MainP_GRAPH, plothandle, VAL_IMMEDIATE_DRAW);
		      plothandle = PlotXY (PMAINP, MainP_GRAPH, &frequencies[catnow*N], &bkg[catnow*N], N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
 		      go = !go ;
		      SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
			  SetCtrlAttribute (PMAINP, MainP_Start_BKG, ATTR_LABEL_TEXT, "Bkg");

		 }


	break;
	}
	return 0;
}

int CVICALLBACK Go_SSCOPE (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{

static int  check, numav, timeout, maxindex, minindex, i,j;
static double max, min, shift, t, abs, bu, bl, tempd, concentration, pressure, Q300, QT;
double a[3], amp, cent, std, res;

switch (event)
	{
		case EVENT_COMMIT:
		     Write_Device(tds210, "ACQ:STATE ON", 12);
			 Write_Device(tds210, "WAIt", 4);
			 Write_Device(tds210, "CURVe?", 6);
	          check = 8001;
	          while (check > 8000) check =ibrd (tds210, readscope, N);
        	  Fmt (writebuffer, "%s<%s%d%s%d%s", "%",N, "d[b1]>%", N,"f");
        	  Scan (readscope, writebuffer, &scope[catnow*N]);
        	 // LinEv1D (bkg, N, factor, 0.0, bkg);
			  MaxMin1D (&scope[catnow*N], N, &max, &maxindex, &min, &minindex);
			  for (i = 0; i < N; ++i){
				  if ((i+maxindex) < N) shiftscope[i] = scope[catnow*N+i+maxindex]-zero[i];
				  if ((i+maxindex) >= N) shiftscope[i] = scope[catnow*N+i+maxindex - (N)]-zero[i];
			  }
			  for (i = 0; i < N; ++i){
				scope[catnow*N+i] = 0;
				if((i >= smoothie) && (i < N-smoothie)) for (j = -smoothie; j < smoothie+1; ++j) scope[catnow*N+i] += shiftscope[i+j];
				scope[catnow*N+i] /= (double)(2*smoothie+1);
	  			} 
 			Q300 = 1.0; QT = 1.0; abs = 0.0;
			for (i = 0; i < N; ++i){
			  tempd = 0.0;
			  if ((bkg[catnow*N+i]-zero[i]) != 0.0) tempd = scope[catnow*N+i]/(bkg[catnow*N+i]-zero[i]);
			  scope[catnow*N+i] = 0.0;
			  if (tempd != 0.0) scope[catnow*N+i] = -log(fabs(tempd));   
	  		  abs += scope[catnow*N+i];
	    	}
			MaxMin1D (&scope[catnow*N], N, &max, &maxindex, &min, &minindex);
  			if (plothandle) plothandle = DeleteGraphPlot (PMAINP, MainP_GRAPH, plothandle, VAL_IMMEDIATE_DRAW);
		    plothandle = PlotXY (PMAINP, MainP_GRAPH, &frequencies[catnow*N], &scope[catnow*N], N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
/*		    a[1] = max; a[2] = 0.2; a[0] = 0.1;
      		NonLinearFitWithMaxIters (x, &scope[catnow*N], shiftscope, N, 100, ZWOF, a, 3, &std);
		
			if (plothandle2) plothandle2 = DeleteGraphPlot (PMAINP, MainP_GRAPH, plothandle2, VAL_IMMEDIATE_DRAW);
		    plothandle2 = PlotXY (PMAINP, MainP_GRAPH, &frequencies[catnow*N], shiftscope, N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
*/	  		
			abs*=df;//fmod(time_base*N/250, period);// factor for # times scanning through line
	  		
			//abs = a[1]*(a[2]/d)/pi;
				
			bu = exp(-fcategy/(0.69*currenttemperature))-exp(-(fcategy+fcatfreq/29979.2458)/(0.69*currenttemperature));
	  		bl = exp(-fcategy/(0.69*300))-exp(-(fcategy+fcatfreq/29979.2458)/(0.69*300));
	  		concentration = abs*(QT*bl)/(path*pow(10, fcatint-14.0)*Q300*bu);
	  		pressure = concentration*300/(currenttemperature*3.217e13); //mTorr at 300 K
	  		SetCtrlVal(PMAINP, MainP_Absorption, abs);
	  		SetCtrlVal(PMAINP, MainP_Concentration, concentration);
	  		SetCtrlVal(PMAINP, MainP_Pressure, pressure);	  
	break;
	}
	return 0;
}

double ZWOF(double x, double *a, int npar)
{
double zwofval, offset;
double w[2], z[2];
     zwofval = 0;
     z[1] = a[2]/d;
     offset = (1/d)*(fcatfreq-frequencies[catnow*N]+a[0])/df;
     z[0] = df * (x - offset);
     zwofz(z, w);
     zwofval = a[1]*w[0]*sqrt (pi);
      
    return zwofval;
}

int CVICALLBACK Go_ZERO (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
static int  check, numav, timeout, maxindex, minindex, i, j;
static double max, min;

switch (event)
	{
		case EVENT_COMMIT:
		 go = !go ;
		 if (!go) {
			 SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
			 SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_LABEL_TEXT, "Zero");
		 } else {
			 SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_CMD_BUTTON_COLOR, VAL_RED);
		 	 SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_LABEL_TEXT, "Zero Stop");
		     Write_Device(tds210, "ACQ:STATE ON", 12);
			 Write_Device(tds210, "WAIt", 4);
			 Write_Device(tds210, "CURVe?", 6);
			  check = 8001;
			  while (check > 8000) check = ibrd (tds210, readscope, N);
        	  Fmt (writebuffer, "%s<%s%d%s%d%s", "%",N, "d[b1]>%", N,"f");
        	  Scan (readscope, writebuffer, zero);

        	  //LinEv1D (zero, N, factor, 0.0, zero);
			  MaxMin1D (zero, N, &max, &maxindex, &min, &minindex);
	  		  for (i = 0; i < N; ++i){
		  		if ((i+maxindex) < N) shiftzero[i] = zero[i+maxindex];
		  		if ((i+maxindex) >= N) shiftzero[i] = zero[i+maxindex -(N)];
		  	  }
	 		 for (i = 0; i < N; ++i){
				zero[i] = 0;
				if ((i >= smoothie) && (i < N-smoothie)) for (j = -smoothie; j < smoothie+1; ++j) zero[i] += shiftzero[i+j];
				zero[i] /= (double)(2*smoothie+1);
			  }   
			  if (plothandle) plothandle = DeleteGraphPlot (PMAINP, MainP_GRAPH, plothandle, VAL_IMMEDIATE_DRAW);
		      plothandle = PlotXY (PMAINP, MainP_GRAPH, &frequencies[catnow*N], zero, N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
 		      go = !go ;
		      SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_CMD_BUTTON_COLOR, VAL_GREEN);
			  SetCtrlAttribute (PMAINP, MainP_Start_ZERO, ATTR_LABEL_TEXT, "Zero");

		 }


	break;
	}
	return 0;
}


int CVICALLBACK Change_Scope (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
int numav;
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(PMAINP, MainP_Time, &time_base);
			Fmt (writebuffer,  "%s<HORIZONTAL:MAIN:SCALE %f[p1e1]", time_base/1000000.);
			Write_Device(tds210, writebuffer, NumFmtdBytes());
            Fmt (writebuffer, "%s<HOR:MAI:POS %f[p2e1]", 5*time_base/1000000.);
        	Write_Device(tds210, writebuffer, NumFmtdBytes()); 

			GetCtrlVal(PMAINP, MainP_Scale, &scale);
			Fmt (writebuffer,  "%s<CH2:SCALE %f[p1e1]", scale/1000.);
			Write_Device(tds210, writebuffer, NumFmtdBytes());
			SetAxisScalingMode (PMAINP, MainP_GRAPH, VAL_LEFT_YAXIS, autoscale, -4*scale, 4*scale);
			factor = (double) 0.04*scale;
			if (control == MainP_UP) yzero += scale;
			if (control == MainP_DOWN) yzero -= scale;
			Fmt (writebuffer,  "%s<CH2:POS %f[p2e1]", (double) yzero/scale);
			Write_Device(tds210, writebuffer, NumFmtdBytes());
			

			GetCtrlVal(PMAINP, MainP_NUMAV, &numav);
			if (numav > 1){
			 Write_Device(tds210, "ACQ:MOD AVE", 11);
			 Fmt (writebuffer,  "%s<ACQuire:NUMAVg %d", numav);
			 Write_Device(tds210, writebuffer, NumFmtdBytes());
			} else {
			 Write_Device(tds210, "ACQ:MOD SAM", 11);
			}	
			GetCtrlVal(PMAINP, MainP_Smoother, &smoothie);
			if (anritsu) scalefrequency();
			
			break;
	}
	return 0;
}

void scalefrequency(void)
{
int i;double t, f, MHzps, sppt; 
 //want MHz/point via (MHz/second)*(seconds/point)
sppt = time_base/250.0e6;
MHzps = modfreq*modamp/1000.0;
df = MHzps*sppt;
//df = (modamp/1000.0)*modfreq*(time_base/250.0)/1.0e6;	 

for (i = 0; i < N; ++i){
	//t = i*(time_base/250.0);
	f = i*df;
	//frequencies[i] = frequency-0.5*(modamp/1000)+(modamp/1000)*modfreq*(fmod(t, period)/1e6);
    frequencies[catnow*N+i] = frequency-0.5*(modamp/1000.0)+fmod(f, modamp/1000.0);
	}
}

int CVICALLBACK Change_Auto (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal (PMAINP, MainP_Autoscale, &autoscale);
			SetAxisScalingMode (PMAINP, MainP_GRAPH, VAL_LEFT_YAXIS, autoscale, 0, 100);
			break;
	}
	return 0;
}

int CVICALLBACK Change_Trace (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal (PMAINP, MainP_TRACE, &acq.type); 
			break;
	}
	return 0;
}

int CVICALLBACK Change_Smooth (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal (PMAINP, MainP_Smoother, &smoothie);
			break;
	}
	return 0;
}


void loadcat(char *catpath)
{
	int i, j, id, sid, ssid, ssidlast;
	static char catline[82], cid[7], lastcid[7], catfreq[13], catint[8], categy[10], catshort[38];
	double fcatfreq, fcatint, minfreq, maxfreq, intthres;

			 cathandle = fopen (catpath, "r");
			 GetCtrlVal(PMAINP, MainP_MINFREQ, &minfreq);
			 GetCtrlVal(PMAINP, MainP_MAXFREQ, &maxfreq);
			 GetCtrlVal(PMAINP, MainP_INT_THRESH, &intthres);
			 EmptyMenu (menubarhandle, MENUBAR_CAT1);
			 catnum = 0;
			 ssid = 0;
			 while (fgets(catline, 82, cathandle) && cathandle){
				Scan (catline, "%s[i44w7]>%s", cid);
				Scan (catline, "%s[w13]>%s", catfreq);
				Scan (catfreq, "%s>%f", &fcatfreq);
				Scan (catline, "%s[i21w8]>%s", catint);
				Scan (catint, "%s>%f", &fcatint);
				Scan (catline, "%s[i31w10]>%s", categy);
				sprintf (catshort, "%s %s %s", catfreq, catint, categy);
				//cid = fabs(cid);

				if ((fcatfreq > minfreq) && (fcatfreq < maxfreq) && (fcatint > intthres)){
				  if (strcmp(cid, lastcid)){
				   id = NewMenuItem (menubarhandle, MENUBAR_CAT1, cid, -1, 0,0,0);
				   sid = NewSubMenu (menubarhandle, id);
				  }  //end if strcmp
				  ssid = NewMenuItem (menubarhandle, sid, catshort, -1, 0, Change_Lines, 0);
				strcpy(lastcid, cid);
				} //end if minmax
				strcpy(lastcat, catpath);
				catnum++;
			 }//end while reading file	 
	
		   
}

int CVICALLBACK Change_Cat (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			/* Open a catalog file
			for each type of species create a menu item
			for each menu item create child items for the transitions*/
			if (FileSelectPopup (lastcat, "*.cat", "*.cat;*.mrg", "Open Catalog List", VAL_LOAD_BUTTON, 0, 0, 1, 0, catpath)) {
			 loadcat(catpath);
			}//end if select file
			break;
	}
	return 0;
}



void CVICALLBACK Change_Lines (int menuBarHandle, int menuItemID, void *callbackData, int panelHandle)
{
static char catshort[33], menu_name[20];
int column;
	GetMenuBarAttribute (menuBarHandle, menuItemID, ATTR_ITEM_NAME, catshort);
	//GetMenuBarAttribute (menuBarHandle, menuItemID, ATTR_SUBMENU_ID, catid);
	Scan (catshort, "%s>%f[p4] %f[p4] %f[p4]", &fcatfreq, &fcatint, &fcategy);
	GetCtrlVal(PMAINP, MainP_CATSLIDE, &column);
	SetCtrlVal(PMAINP, MainP_FREQUENCY, fcatfreq);
	SetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (column, 1), &catshort[0]);
	SetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (column, 2), &catshort[11]);
	SetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (column, 3), &catshort[20]);
	SetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (column, 4), menuItemID);

	catnow = menuItemID;  
	Change_Frequency(PMAINP, MainP_FREQUENCY, 1, 0, 0, 0);

}

int CVICALLBACK Change_Column (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int val;
	static char catshort[33];
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(PMAINP, MainP_CATSLIDE, &val);
			GetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (val, 4), &catnow);
			if (catnow) {
			 GetTableCellVal (PMAINP, MainP_CATTABLE, MakePoint (val, 1), catshort);
			 Scan (catshort, "%s>%f[p4] %f[p4] %f[p4]", &fcatfreq, &fcatint, &fcategy);
			 SetCtrlVal(PMAINP, MainP_FREQUENCY, fcatfreq);
			 Change_Frequency(PMAINP, MainP_FREQUENCY, 1, 0, 0, 0);
			}
			break;
	}
	return 0;
}


int CVICALLBACK Change_Pathlength (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(panel, control, &path);
			break;
	}
	return 0;
}

int CVICALLBACK Change_Numpts (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(panel, control, &N);
			dimension_arrays(catnum, N);
			initScope();
			scalefrequency();
			break;
	}
	return 0;
}





int CVICALLBACK Show_temp_gragh (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal (panel, control, &stripchart);
			if (stripchart) {
			DisplayPanel (PTEMPLOG);
			loadlog();
			} else {
			HidePanel (PTEMPLOG);
				
			}
			break;
	}
	return 0;
}

void loadlog(void)
{
	FILE* logfile;
	static char logline[80];
	int i;
	double temps[8];
			logfile = fopen ("c:\\My Projects\\collisions.log", "r") ;
			while ((fgets (logline, 80, logfile)) != NULL ){
			//	sscanf (logline, "8%lf\n", temps);
				Fmt (temps, "%8f<%s", logline);
				temps[1] = temps[2];
				temps[2] = temps[4];
				temps[3] = temps[6];
				PlotStripChart (PTEMPLOG, TEMPLOG_STRIPCHART, temps, 4, 0, 1, VAL_DOUBLE);
				for (i = 1; i < interval; ++i) PlotStripChart (PTEMPLOG, TEMPLOG_STRIPCHART, temps, 4, 0, 1, VAL_DOUBLE);
				//try to match slope to current time interval
			}
			fclose(logfile);
}
int CVICALLBACK Close_temps (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_COMMIT:
			SetCtrlVal(PMAINP, MainP_TEMPGRAPH, 0);
			Show_temp_gragh (PMAINP, MainP_TEMPGRAPH, 1, 0 ,0 ,0);
			break;
	}
	return 0;
}

int CVICALLBACK change_temp_graph (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	double max, min;
	int t;
	switch (event)
	{
		case EVENT_COMMIT:
			GetCtrlVal(PTEMPLOG, TEMPLOG_MAXTEMP, &max);
			GetCtrlVal(PTEMPLOG, TEMPLOG_MINTEMP, &min);
			GetCtrlVal(PTEMPLOG, TEMPLOG_Time, &t);
			SetAxisScalingMode (PTEMPLOG, TEMPLOG_STRIPCHART, VAL_LEFT_YAXIS, VAL_MANUAL, min, max);
	        SetCtrlAttribute (PTEMPLOG, TEMPLOG_STRIPCHART, ATTR_POINTS_PER_SCREEN, t);
			SetCtrlAttribute (PTEMPLOG, TEMPLOG_STRIPCHART, ATTR_XAXIS_GAIN, 10.0);
			loadlog();
			break;
	}
	return 0;
}

int CVICALLBACK Change_Gain (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int i;
	double val;
	switch (event)
	{
		case EVENT_COMMIT:
		GetCtrlVal (panel, control, &val);
		for (i = 0; i < numtemps; ++i){
			SetCtrlAttribute (PTEMPLOG, TEMPLOG_T1_GAUGE + fmod(i,4), ATTR_MAX_VALUE, 50*val);	
			SetCtrlAttribute (PTEMPLOG, TEMPLOG_T1_GAUGE + fmod(i,4), ATTR_MIN_VALUE, -50*val);	
		}
		break;
	}
	return 0;
}

void InitDAQ (void)
{
int i, j, k, l;
const double val[4]; 
double max, min;
char chan_name[9];
		{
		acq.numvolts = 0;
		DAQmxClearTask (DAQInputs);
		DAQmxCreateTask ("", &DAQInputs); 
		for (j = 0; j < 8; ++j){
			GetCtrlVal(PMAINP, MainP_DAQ1+j, &gain[j]);
			if (gain[j]) {
				acq.numvolts = acq.numvolts + 1;
			    sprintf (chan_name, "Dev1/ai%d", j);
				max = (double) 0.001*gain[j];
				//scale from 1,2,20,200 to 10.0,5.0,0.5,0.05 and set ranges for channels
				DAQmxCreateAIVoltageChan (DAQInputs, chan_name, "", DAQmx_Val_NRSE, -max, max, DAQmx_Val_Volts, "");
			} //end if gain
		} //end for j
	    acqdata.scope = malloc (N * acq.numvolts * (sizeof(float64)));
		aqrd.scope = malloc (N * acq.numvolts * (sizeof(float64)));
		
		//DAQmxClearTask (DAQTrig);
		//DAQmxCreateTask ("DAQTrigger", &DAQTrig);
        //DAQmxCfgAnlgEdgeStartTrig (DAQTrig, "APFIO", DAQmx_Val_FallingSlope, 0.0);
		
		//DAQmxCreateCICountEdgesChan (DAQTrig, "Dev1/ctr0", "", DAQmx_Val_Rising, 0, DAQmx_Val_CountUp);
	    DAQmxCfgSampClkTiming (DAQInputs, "", 8*N/acq.numvolts, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, N);
		//DAQmxCfgDigEdgeStartTrig (DAQInputs, "/Dev1/PFI8", DAQmx_Val_Rising);
	 	
		
		   
		}	  
}


int CVICALLBACK Change_DAQ (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
int ret;

	ret = 1;
   return ret;
}

int acqthread(void *dumy)
{ // mother function for data acquisition thread 
static char  buffer[100];
static int  check, numav, timeout, maxindex, minindex, i, j, count, nscope;
int NN;
static double   max, min, shift, t, abs, bu, bl, tempd;
	

  for(;;){
    while (acq.onoff == 0){
      CmtReadTSQData (acqcmdTSQ, &acq, 1, TSQ_INFINITE_TIMEOUT, NULL);
//      if (acq.onoff == 0) return 0;  /* terminate thread */
	  count = 0;
    }
	 count++; 
	 acq.smooth = smoothie;
	 acq.frequency = fcatfreq;
	 acq.egy = fcategy;
	 acq.intensity = fcatint;
	 acq.temperature = currenttemperature;
	 acq.Q300 = 1.0;
	 acq.QT = 1.0;
	 
	 if (tds210){
      Write_Device(tds210, "ACQ:STATE ON", 12);
	  Write_Device(tds210, "WAIt", 4);
	  Write_Device(tds210, "CURVe?", 6);

	  ibrd (tds210, readscope, N);
	  Fmt (writebuffer, "%s<%s%d%s%d%s", "%",N, "d[b1]>%", N,"f");
	  Scan (readscope, writebuffer, &scope[catnow*N]);
 
	  //LinEv1D (scope, N, factor, 0.0, scope);
	  MaxMin1D (&scope[catnow*N], N, &max, &maxindex, &min, &minindex);
	  for (i = 0; i < N; ++i){
		  if ((i+maxindex) < N) shiftscope[i] = scope[catnow*N+i+maxindex]-zero[i];
		  if ((i+maxindex) >= N) shiftscope[i] = scope[catnow*N+i+maxindex -(N)]-zero[i];
	  }      
	  
	  for (i = 0; i < N; ++i){
		scope[catnow*N+i] = 0;
		if ((i >= acq.smooth+7) && (i < (N-acq.smooth-7))){
		 for (j = -acq.smooth; j < acq.smooth+1; ++j) scope[catnow*N+i] += shiftscope[i+j];
		 scope[catnow*N+i] /= (double)(2*acq.smooth+1);
		} 
	  }
	  
//	  if (acq.type == 1) for (i = 0; i < N; ++i)  scope[i] = 100.0*((scope[i])/(shiftbkg[i]-shiftzero[i]));

//	  if (acq.type == 2){
		abs = 0.0;
		for (i = 0; i < N; ++i){
		  tempd = 0.0;
		  if ((shiftbkg[i]-zero[i]) != 0.0) tempd = scope[catnow*N+i]/(bkg[catnow*N+i]-zero[i]);
		  scope[catnow*N+i] = 0.0;
		  if (tempd != 0.0) scope[catnow*N+i] = -log(fabs(tempd));   
	  	  abs += scope[catnow*N+i];
	    }
//	  }
	  MaxMin1D (&scope[catnow*N], N, &max, &maxindex, &min, &minindex);
	 }  //end if tds210
	 
	 DAQmxReadAnalogF64 (DAQInputs, N, 1.0, DAQmx_Val_GroupByChannel, scope, N*acq.numvolts, &NN, 0);
	 //LinEv1D (scope, N, df, acq.frequency, scope);

	  acqdata.scope = scope;
	  acqdata.absorption = abs*df;//fmod(time_base*N/250, period);// factor for # times scanning through line
	  bu = exp(-acq.egy/(0.69*acq.temperature))-exp(-(acq.egy+acq.frequency/29979.2458)/(0.69*acq.temperature));
	  bl = exp(-acq.egy/(0.69*300))-exp(-(acq.egy+acq.frequency/29979.2458)/(0.69*300));
	  acqdata.concentration = pi*pi*acqdata.absorption*(acq.QT*bl)/(path*pow(10, acq.intensity-14.0)*acq.Q300*bu);
	  acqdata.pressure = acqdata.concentration*300/(acq.temperature*3.217e13); //mTorr at 300 K
	  acqdata.num = count;
/*	  acqdata.pressure = acqdata.absorption*3.14159/(102.458*path*pow(10,acq.intensity));
	  acqdata.concentration = acqdata.pressure*3.217e16;	*/
      CmtWriteTSQData (acqdataTSQ, &acqdata, 1, TSQ_INFINITE_TIMEOUT, NULL);
  
  }
  return 0;
}

void  CVICALLBACK acqCallback(int qHandle, unsigned int event, int value, void *callbackData)
{
	// TSQ callback for plotting
  while (value) {
    --value;
    if (CmtReadTSQData (qHandle, &aqrd, 1, 100, 0) <= 0) break;

	if (plothandle) plothandle = DeleteGraphPlot (PMAINP, MainP_GRAPH, plothandle, VAL_IMMEDIATE_DRAW);
	//plothandle = PlotY (PMAINP, MainP_GRAPH, aqrd.scope, N, VAL_DOUBLE, VAL_THIN_LINE, VAL_NO_POINT, VAL_SOLID, VAL_CONNECTED_POINTS, VAL_BLACK);
	plothandle = PlotXY (PMAINP, MainP_GRAPH, &frequencies[catnow*N], aqrd.scope, N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
    //plothandle = PlotXY (PMAINP, MainP_GRAPH, &aqrd.scope[0], &aqrd.scope[N], N, VAL_DOUBLE, VAL_DOUBLE,VAL_SCATTER, VAL_SMALL_SOLID_SQUARE, VAL_SOLID, 1, VAL_BLACK);
    SetCtrlVal(PMAINP, MainP_COUNTER, acqdata.num);
	SetCtrlVal(PMAINP, MainP_Absorption, acqdata.absorption);
	SetCtrlVal(PMAINP, MainP_Concentration, acqdata.concentration);
	SetCtrlVal(PMAINP, MainP_Pressure, acqdata.pressure);
	p5 = p4; p4 = p3; p3 = p2; p2 = p1;
	p1 = acqdata.pressure;
 	SetCtrlVal(PMAINP, MainP_Pressure_2, (p5+p4+p3+p2+p1)/5.0);
  }
  
  //end if event
}
