/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1991 by John E. Lloyd.				    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Program for testing the RCI system wall clock, at both the
   planning and control levels.
 */

#include <stdio.h>
#include <signal.h>
#include "../h/timeval.h"
#include "../h/cdefs.h"
#include "../h/rci.h"
#include "wctest.h"

struct timeval rciWallClock();

int rate = 50;
int delay = 100;
WC_BLK *wbk;

onInt()
{
	rciRelease();
	printTally(wbk);
	exit (0);
}

printTally(wbk)
WC_BLK *wbk;
{
	int n;
	double sum;

	n = wbk->count;
	sum = timevalToDouble(wbk->tvsum);
	printf ("\n%d counts:\n", n);
	printf ("max = %d.%06d\n", wbk->tvmax.tv_sec, wbk->tvmax.tv_usec);
	printf ("min = %d.%06d\n", wbk->tvmin.tv_sec, wbk->tvmin.tv_usec);
	printf ("avg = %8.6f\n", sum/n);
}

extern controlFxn();

main(argc, argv)
int argc;
char **argv;
{
	RCI_DESC *td;
	int planningLevelCheck = 1;
	int executeCount = 0;
	int automatic = 0;
	struct timeval maxError;
	struct timeval minError;
	static float napVals[] = 
	 {  0.01,
	    0.02,
	    0.05,
	    0.10,
	    0.20,
	    0.50,
	    1.11,
	    2.22,
	    5.55,
	 };
	static float autoNapVals[] = 
	 {  0.01,
	    0.02,
	    0.05,
	    0.11,
	    0.22,
	    0.33,
	 };
	int k;

	rciSetOptions (EXIT_ON_ERROR);
	wbk = (WC_BLK*)allocMem (NULL, sizeof(WC_BLK), UNDEF);

	argc--; argv++;
	while (argc > 0)
	 { if (ARGUMENT("-c"))
	    { planningLevelCheck = 0;
	    }
	   else if (ARGUMENT ("-a"))
	    { argc--; argv++;
	      if (argc == 0)
	       { argc = -1;
		 break;
	       }
	      automatic = atoi(*argv);
	    }
	   else if (ARGUMENT ("-e"))
	    { argc--; argv++;
	      if (argc == 0)
	       { argc = -1;
		 break;
	       }
	      executeCount = atoi(*argv);
	      planningLevelCheck = 0;	      
	    }
	   else if (ARGUMENT ("-r"))
	    { argc--; argv++;
	      if (argc == 0)
	       { argc = -1;
		 break;
	       }
	      rate = atoi(*argv);
	    }
	   else if (ARGUMENT ("-d"))
	    { argc--; argv++;
	      if (argc == 0)
	       { argc = -1;
		 break;
	       }
	      delay = atoi(*argv);
	    }
	   else
	    { argc = -1;
	      break;
	    }
	   argc--; argv++;
	 }
	if (argc < 0)
	 { fprintf (stderr, "\
usage: wallClockTest [-c] [-a <numtests>] [-r <rate>] \n\
		     [-d <delay>] [-e <executeCount>]\n");
	   exit (-1);
	 }

	wbk->delay = delay;
	td = rciCreate ("foo", 0);

	if (planningLevelCheck)
	 { if (automatic)
	    { timerclear (&maxError);
	      timerclear (&minError);
	      for (k=0; k<automatic; k++)
	       { struct timeval tv1, tv2, tv3, error, zero;
		 float napTime;
   
		 napTime = autoNapVals[k % ARRAY_SIZE(autoNapVals)];
		 tv1 = rciWallClock();
		 nap (napTime);
		 tv2 = rciWallClock();
		 tv3 = diffTimeval(tv2, tv1);

		 /* compute error */

		 error = diffTimeval(tv3, doubleToTimeval((double)napTime));
		 timerclear (&zero);
		 if (timercmp (&error, &zero, <))
		  { error = negateTimeval(error);
		    if (timercmp (&error, &minError, >))
		     { minError = error;
		     }
		  }
		 else
		  { if (timercmp (&error, &maxError, >))
		     { maxError = error;
		     }
		  }
	       }
	      printf (
"%d tests, max neg. error = %d.%06d max pos. error = %d.%06d\n", 
		      automatic, minError.tv_sec, minError.tv_usec,
				 maxError.tv_sec, maxError.tv_usec);
	    }
	   else
	    { while (1)
	       { for (k=0; k<ARRAY_SIZE(napVals); k++)
		  { struct timeval tv1, tv2, tv3;
		    float napTime;
      
		    napTime = napVals[k];
		    tv1 = rciWallClock();
		    nap (napTime);
		    tv2 = rciWallClock();
		    tv3 = diffTimeval(tv2, tv1);
      
		    printf ("naptime = %g, timeval = %d.%06d\n",
			     napTime, tv3.tv_sec, tv3.tv_usec);	      
      
		  }
	       }
	    }
	 }
	else if (executeCount)
	 { for (k=0; k<executeCount; k++)
	    { rciExecute (td, controlFxn, (int)wbk, NULL);
	    }
	   printTally (wbk);
	 }
	else
	 { printf ("rate = %d msec., delay count = %d\n", rate, delay);

	   rciControlFxns (td, NULLF, controlFxn, NULLF, (int)wbk);
	   rciRate (td, rate, 0);
	   rciScheduling (td, ON_CLOCK, 0);
	   rciStart (~0);

	   signal (SIGINT, onInt);
	   while(1)
	      ;

	   rciRelease();
	 }
}
