#define	TEMP_FILE	"\\temp.ray"
#define THROWAWAY	"\\throwa.way"

/* OPRA Data Acquisition Program */
#define ZOFFSET  20.0
#define	ZLOW	-20.0
#define ZHIGH 	 60.0
#define ZSCALE	16./(ZHIGH - ZLOW)

#define NOTAPE

#include        <math.h>
#include        <conio.h>       /* for getch, kbhit */
#include        <stdio.h>       /* for malloc */
#include        <dos.h>
#include        <signal.h>
#include	<time.h>
#include	<unistd.h>
#include	<allegro.h>

#define EXTERN
#include        "..\include\globals.h"
extern double trcorrtog;


#define         PPI     0
#define         RHI     1

unsigned long wrtcounter = 0;
int nodisplay = 1, radiate = 0;
double DACVOLTAGE = -4.2;
DISPLAY *remdisp;

main(argc,argv)
char    *argv[];
int     argc;
{
	char    c, fname[20];
	DWELL   *dwell;
	RADAR   *radar;
	CONFIG  *config;
	PIRAQ   *piraq;
	DISPLAY *disp;
	PACKET  *packet;
	float   *prods, *prptr;
	double  zsave;
	int     rayv, gate,oldbutton=0, ascptr;
	int     type=PPI,dispnum='1',dchange=0,pmode,singlefilter;
	int 	   togcnt = 0, counter = 0, runcnt = 0;


	int       gates_noclut, gates_clut;
	int       noafc = 0;
	double    dopp = 0.0;
	FILE	*tmpfp, *thrwfp;


	int i, j, test=1,sync,oldtime,bidelay,leftover,xmit,event;
	unsigned int    itime;
	unsigned short  subsec;
	double crap,vconst;
	struct tm *ascz;


	ascptr = 0;

	if(argc > 1)
	{
		if(!strncmp("-G", argv[1]))nodisplay = 0;
		if(!strncmp("-g", argv[1]))nodisplay = 0;
		if(!strncmp("-A", argv[1]))nodisplay = 2;
		if(!strncmp("-a", argv[1]))nodisplay = 2;
	}

	gates_noclut = gates_clut = 200;

	signal(SIGFPE,SIG_IGN);

	if((prods = (float *)malloc(sizeof(float) * 1200 * 8)) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((dwell = (DWELL *)malloc(sizeof(DWELL))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((disp = (DISPLAY *)malloc(sizeof(DISPLAY))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((radar = (RADAR *)malloc(sizeof(RADAR))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((config = (CONFIG *)malloc(sizeof(CONFIG))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((piraq = (PIRAQ *)malloc(sizeof(PIRAQ))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	if((packet = (PACKET *)malloc(sizeof(PACKET))) == NULL)
	{puts("not enough memory"); exit(1);
	}

	/* read in the dsp configuration file */
	readconfig("",config);
	singlefilter = config->clutterfilter;

	/* set the pointers in the piraq structure based on the configuration */
	setpiraqptr(config,piraq);

	/* load the dsp code into the dual port ram */
	initsystem(config);
	cleardpram(config,piraq);
	load(config,piraq);

	/* put all configuration parameters into the piraq's dual port ram */
	setdpram(config,piraq);

	/* read in the radar configuration file */
	readradar("",radar);

	/* read in the display configuration file */
	readdisplay("",disp);

	if(!timerset(config)) {printf("EXEC: Error setting timer\n"); exit(1);
	}      /* set up the range gate timer */
	if(!start(config))  {printf("EXEC: Could not start PIRAQ\n"); exit(1);
	}        /* start the range gate timer and DSP */

	/* initialize functions such as gps,serial,display,tape,disk after this */

	/* get a dwell structure header filled so the display can initialize */
	/* by using the header of a bogus dwell */
	fillheader(dwell,piraq,config);  /* fill the dwell header */

	/* initialize SCSI tape drive */

#ifndef NOTAPE
	init_tape();
#endif

	/* Force Vert Pointing mode */
	disp->type |=2; /* Put on the grid bit */
	disp->type |=4; /* Put on the VP bit */
	
	/* Record data to disk at startup: added 9/18/99 GRG */
	disp->recording = 2;

	if(!nodisplay)
	{
		if(!init_display(radar,dwell,disp))
		{
			printf("could not open display lookup file\n");
			closeall();
			exit(1);
		}
	}
	if(nodisplay == 1)
		printf("EXEC running, hit Q to exit\n");

	/* calculate this constant just once */
	vconst = 128.0 * (2.0 * radar->frequency * 2.0 * M_PI * dwell->header.prt) / C / M_PI;

	/* Ensure that wrtollg.trg does NOT exist */
	if(exists("\\wrtoggle.trg"))
	{
		unlink("\\wrtoggle.trg");
	}


	pmode = *piraq->dataformat;
	zsave = disp->rgpp/(3*1.414);
	/*  GRG 4/19/98 disp->rgpp =zsave; */
	
	disp->displayparm = 4;	/* Force dBZ for default */
	
	do
	{
		/* Test for disk write toggle flag */
		if(exists("\\wrtoggle.trg"))  /* Test for existence of the trigger file */
		{
			unlink("\\wrtoggle.trg"); /* Delete the toggle trigger file */

			if(togcnt == 0) /* Don't let it trigger more than once */
			{
				disp->recording = (disp->recording == 2) ? 0 : 2;
				togcnt++;
			}
		}
		else	/* If trigger file doesn't exist, zero the toggle count */
		{
			togcnt = 0;
		}

		/* if c = 0 and there is already is another character, then */
		c = kbhit() ? toupper(getch()) : 1;

		/* a function key was hit */
		if(c == 0)
		{
			c = getch() - 0x3B;    /* parse the function key */
			if(c < 6  || (c < 8 && dwell->header.dataformat == DATA_POL1))
			{
				disp->displayparm = c;
				ascptr = (int)c;
				if(!nodisplay)selections(disp);
			}
			/* This line eliminates crash if tape selected with F10 */
			if(c==9)c=8;
			switch(c) /* recording to tape (3) or disk (2) */
			{   case 8:
				disp->recording = (disp->recording == 2) ? 0 : 2;
				write_disk(1,dwell,radar,config->outfilename);  /* write RADAR to disk */
				break;
			case 9:
				disp->recording = (disp->recording == 3) ? 0 : 3;
				write_tape(1,dwell,radar);  /* write a RADAR struct to tape */
				break;
			}
			c = 1;        /* reset c to benign value */
		}

		if(c == 'G')   savescr(dwell->header.time);
		
	       /* Toggle TR correction */
		if(c == 'X')   trcorrtog = trcorrtog == 1? 0: 1; 
	

		if(c == '1')   disp->rgpp *= 2;
		if(c == '2')   disp->rgpp /= 2;

		/* Remove these options for VP */
		/*      if(c == '3')   disp->type ^= 2;*/   /* flip the grid bit */
		/*      if(c == '4')   disp->type ^= 4;*/   /* vertical profile bit */


		/* dac output voltage */
		if(c == '>')     dac(DACVOLTAGE+=0.05);
		if(c == '<')     dac(DACVOLTAGE-=0.05);

		/* change gate spacing on the fly */
		if (c == '[' || c == ']')
		{
			switch(disp->recording)  /* write a closing radar structure*/
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename);  break;
			case 3:      write_tape(1, dwell, radar);  break;
			default:     break;
			}
			if (c == ']')   config->pulsewidth +=2;
			if (c == '[')   config->pulsewidth -=2;
			if (config->pulsewidth < 2)   config->pulsewidth = 2;
			/* the following code will set up a scan for full amb range */
			if (config->pulsewidth > 92 && config->clutterfilter == 0)
			{
				config->pulsewidth = 94; /* set up xxxm gates */
				config->gates = gates_noclut;
			}
			if (config->pulsewidth > 62 && config->clutterfilter == 1)
			{
				config->pulsewidth = 64; /* set up xxxm gates */
				config->gates = gates_noclut;
			}
			switch (disp->recording)  /* write a closing radar structure*/
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename);  break;
			case 3:      write_tape(1, dwell, radar);  break;
			default:     break;
			}
			stop(config);
			/* put all configuration parameters into the piraq's dual port ram */
			setdpram(config, piraq);
			timerset(config);   /* set up the range gate timer */
			if (!start(config))  exit(1); /* start the range gate timer */
			/* get a dwell structure header */
			/* filled so the display can */
			/* initialize by using the header */
			/* of a bogus dwell */
			fillheader(dwell, piraq, config);     /* fill the dwell header */
			//         init_disp_scales(radar, dwell, disp);
		}
		if (c == 'S' || c == 'D')
		{
			switch (disp->recording)
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename);  break;
			case 3:      write_tape(1, dwell, radar);  break;
			default:     break;
			}
			if (c == 'D')   config->hits *=2;
			if (c == 'S')   config->hits /=2;
			if (config->hits < 32)     config->hits = 32;
			if (config->hits > 1024)   config->hits = 1024;
			setdpram(config, piraq);
		}

		if (c == ',' || c == '.')
		{
			switch (disp->recording)
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename);break;
			case 3:      write_tape(1, dwell, radar); break;
			default:     break;
			}
			if (c == ',')   config->gates -=10;
			if (c == '.')   config->gates +=10;
			setdpram(config, piraq);
		}


		if (c == 'M' || c == 'N')
		{
			if (c == 'M') config->tsgate +=1;
			if (c == 'N') config->tsgate -=1;
			if (config->tsgate < 1)   config->tsgate = 1;
			if (config->tsgate > config->gates -1)  config->tsgate = config->gates -1;
			config->timeseries = 1;
			setdpram(config, piraq);
		}
		if (c == 'H' || c == 'J')
		{
			if (c == 'J')   config->tsgate +=10;
			if (c == 'H')   config->tsgate -=10;
			if (config->tsgate < 1)   config->tsgate = 1;
			if (config->tsgate > config->gates -1)  config->tsgate = config->gates -1;
			config->timeseries = 1;
			setdpram(config, piraq);
		}


		if(c == 'F')   disp->fakeangles = 1 - disp->fakeangles;
		if(c == 'T')   {disp->threshold += 0.05; if(disp->threshold > .99) disp->threshold=.99;
		}
		if(c == 'U')   disp->threshold = 0.0;

		/*chang*/
		if (c == 'C')
		{
			switch (disp->recording)  /* write a closing radar structure*/
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename);break;
			case 3:      write_tape(1, dwell, radar);break;
			default:     break;
			}
			config->clutterfilter ^= 1;
			if (config->clutterfilter == 1)   config->gates = gates_clut;
			if (config->clutterfilter == 0)   config->gates = gates_noclut;
			switch (disp->recording)  /* write a closing radar structure*/
			{
			case 2:      write_disk(1, dwell, radar, config->outfilename); break;
			case 3:      write_tape(1, dwell, radar); break;
			default:     break;
			}
			stop(config);
			/* put all configuration parameters into the piraq's dual port ram */
			setdpram(config, piraq);
			timerset(config);   /* set up the range gate timer */
			if (!start(config))  exit(1); /* start the range gate timer */
			/* get a dwell structure header */
			/* filled so the display can */
			/* initialize by using the header */
			/* of a bogus dwell */
			fillheader(dwell, piraq, config);     /* fill the dwell header */
			//         init_disp_scales(radar, dwell, disp);
		}

		if (c == 'A' && config->pcorrect)
		{
			if(!nodisplay)close_display();
			afclock(config, piraq);

			if (!nodisplay && !init_display(radar, dwell, disp))
			{
				closeall();
				printf("could not open display lookup file\n");
				exit(1);
			}
		}

		/* some of these parameters are no longer used */
		/* Remove option for VP radars
		if(c == 'P' && disp->type != PPI)              {disp->type = PPI; dchange = 1; c = dispnum;}
		if(c == 'R' && disp->type != RHI)              {disp->type = RHI; dchange = 1; c = dispnum;}
		*/
		/* DEBUG This permanently kills the TX...can't restart it
		The reason is: there is no trigger to the DSP and so the wait cycle
		stalls it out.  Need to set flags to bypass wait when it's in stop
		mode

		if(c == '!')
		{
		if(radiate)
		{
		radiate = 0;
		Prf(8.0E+06/(float)config->prt, 1.0, 0);
		}
		else
		{
		radiate = 1;
		Prf(8.0E+06/(float)config->prt, 1.0, 1);
		}
		}
		*/
		if(c >= '0' && c <= '9' && c != dispnum) dchange = 1;

		if (c == 'O')
		{
			config->pcorrect = 1 - config->pcorrect;
			setdpram(config, piraq);
		}
		if(c == 'K') /* Kill OPRA */
		{
			closeall();
			exit(2);
		}


# ifdef notdef
		/* if left mouse button was just clicked */
		gate = disp->mouserange / (C * 0.5 * dwell->header.rcvr_pulsewidth);
		if(disp->mousebutton & ~oldbutton & LEFTBUTTON)
			if(gate < config->gates)
			{
				config->tsgate = gate;
				setdpram(config,piraq);
			}
		if(disp->mousebutton & ~oldbutton & RIGHTBUTTON)
		{
			config->timeseries ^= 1;
			setdpram(config,piraq);
		}
		/* update the mouse button memory */
		oldbutton = disp->mousebutton;
# endif

		if(!wait(config,piraq))  break;

		if(config->pcorrect && config->gate0mode)    afc(config,piraq);

		filldwell(dwell,piraq,config); /* create a dwell structure in full */
		dwell->header.dacvoltage = DACVOLTAGE; /* GRG 9/23/99 */

		products(dwell,radar,prods);  /* compute scientific radar parameters */
		/*
		This section writes a data ray for remote and a throwaway file
		to let remote know that it is done writing.   Remote will then read the
		data file and delete the throwaway.
		*/

		tmpfp = fopen(TEMP_FILE, "wb");
		fwrite(radar,radar->recordlen,1,tmpfp);
		fwrite(dwell,dwell->header.recordlen,1,tmpfp);
		fwrite(disp,sizeof(DISPLAY),1,tmpfp);
		fclose(tmpfp);

		thrwfp = fopen(THROWAWAY, "wb");
		fwrite(radar,radar->recordlen,1,thrwfp);
		fclose(thrwfp);
		/* End of remote communication section */

		if(disp->recording == 2)     write_disk(2,dwell,radar,config->outfilename);  /* write to disk */
		if(disp->recording == 3)     write_tape(2,dwell,radar);  /* write to tape */

		switch(nodisplay)
			{
			case 0:
				display(dwell,disp,prods);  /* write one dwell to display */
				break;
			case 1:
				printf("%10d\n", ++wrtcounter);
				break;
			case 2:
				zprint(prods, dwell, disp);
				break;
			default:
			}

		/* Test for kill flag (existence of "killopra.fil") */
		if(exists("\\killopra.fil"))  /* Test for existence of the trigger file */
		{
			unlink("\\killopra.fil"); /* Delete the kill trigger file */
			closeall();
			exit(2);
		}
		/* Test for quit flag (existence of "qexec.tog") */
		if(exists("\\qexec.tog"))  /* Test for existence of the trigger file */
		{
			unlink("\\qexec.tog"); /* Delete the toggle trigger file */
			closeall();
			exit(0);
		}
	}while(c != 'Q');
	closeall();
	exit(0);
}

void closeall(void)
{
	Prf(1000,1,0);
	if(!nodisplay)close_display();
	printf("EXEC terminated\n");
	close_disk();
	close_tape();
	savev();
}

zprint(float *prods, DWELL *dwell, DISPLAY *disp)
{
	int i, rayv, ascptr;
	struct tm *ascz;
	float *prptr;
	char curchar, colchars[16] = {'a','b','c','d','0','1','2','3','4','5','6','7',
			'8','9','A','B'};

	ascz = gmtime((time_t *)&dwell->header.time);
	prptr = prods;
	ascptr = 4;
	printf("%02d%02d%02d:", ascz->tm_hour, ascz->tm_min, ascz->tm_sec);
	for(i=0; i < 70; i++)
	{
		rayv = ((int)((*(prptr + ascptr) + ZOFFSET)*ZSCALE))&0xF;
		curchar = colchars[rayv];
		if(*(prptr + ascptr) > ZHIGH)curchar = '^';
		if(*(prptr + ascptr) < ZLOW)curchar = '.';
		if(*(prptr + 2) < disp->threshold)curchar = '-';
		printf("%1c", curchar);
		prptr += PRODS_ELEMENTS;
	}
	printf("\n");
	if(ascz->tm_sec%10 == 0)
		printf("  km-> 0----^---1.5---^---3.0---^---4.5---^---6.0---^---7.5---^---9.0 %s\n",
			disp->recording != 2? "Rec off": "To disk");
}

