/*===========================================================================
  calib.c: program to demonstrate calibration and use of STAT! timing
  functions
  =========================================================================*/
#include <dos.h>
#include <graphics.h>
#include <stat.h>

#define ZEROWORD 0x0000
#define ALLTIMERS TF_T1|TF_T2|TF_T3|TF_T4|TF_T5
#define TIMERS12 TF_T1|TF_T2
#define STATIOADR 0x0250
#define F1_RES 250


/*---------------------------------------------------------------------------
   CalibrateOverhead:

   Function to determine the average overhead incurred by a call to
   LoadTimers() followed by a call to SaveTimers();  This function assumes
   that the STAT! board has already been initialized.

   Arguments: n - number of samples to average

   Return value = average overhead in nanoseconds
  -------------------------------------------------------------------------*/

  float CalibrateOverhead(unsigned n)
  {
  unsigned i;
  unsigned diff = 0;

  /* Configure all timers to count up in binary, from freq. generator 1 */

  ConfigTimer(TN_T1,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);
  ConfigTimer(TN_T2,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);
  ConfigTimer(TN_T3,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);
  ConfigTimer(TN_T4,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);
  ConfigTimer(TN_T5,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);

  /* place 0 in all timer load registers */

  WriteTimerLoad(TN_T1,ZEROWORD);
  WriteTimerLoad(TN_T2,ZEROWORD);
  WriteTimerLoad(TN_T3,ZEROWORD);
  WriteTimerLoad(TN_T4,ZEROWORD);
  WriteTimerLoad(TN_T5,ZEROWORD);

  /* Start all timers */

  ArmTimers(ALLTIMERS);

  /* loop - each time through, measure difference, add it to diff */

  disable();          /* disable pesky timer tick and RTC interrupts */
  for(i=0;i<n;i++){
    LoadTimers(ALLTIMERS);              /* zero the timers */
    SaveTimers(ALLTIMERS);              /* sample the timers */
    diff += ReadTimerHold(TN_T1);       /* read sampled value from timer1 */
    };
  enable();          /* reenable pesky interrupts */

  /* Turn off timers */

  DisarmTimers(ALLTIMERS);

  /* return average overhead */

  return(F1_RES*(float)diff/(float)n);
  };

/*-------------------------------------------------------------------------*/
/* Program to demonstrate function CalibrateOverhead()                     */
/* Measure execution time required to draw a circle                        */
  main()
  {
  int j;
  float overhead;
  unsigned long RawCircleTime;
  float CookedCircleTime;
  int gdriver = DETECT, gmode, errorcode; /* BGI init variables */

  /* initialize STAT! board */

  SetStatAdd(STATIOADR);
  if(!InitStat()){
    printf("STAT! board Init problem.  Press key to continue...\n");
    getch();
    };

  /* Determine Load/Save overhead.  Do this first since this function alters
     configuration of timers */

  overhead = CalibrateOverhead(100); /* average over 100 measurements */

  /* Configure timers 1 & 2 as a cascaded counter to count up in binary,
     with 250 nanosecond resolution.  Counter 1 is LSW, counter 2 is MSW */

  ConfigTimer(TN_T1,TS_F1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);
  ConfigTimer(TN_T2,TS_TNM1,TC_REPEAT,TD_UP,TB_BIN,TM_OFF);

  /* Load timers 1 & 2 LOAD registers with zeroes in preparation for time
     measurement - go ahead and start timers */

  WriteTimerLoad(TN_T1,ZEROWORD);
  WriteTimerLoad(TN_T2,ZEROWORD);
  ArmTimers(TIMERS12);

  /* In this section we will measure how long it takes to draw a circle */

  initgraph(&gdriver, &gmode, "c:\\lnguages\\bc\\bgi");
  LoadTimers(TIMERS12); /* start measurement now */
  circle(300,200,50);
  SaveTimers(TIMERS12); /* sample elapsed time to draw circle */
  getch();              /* wait for user to finish looking at circle */
  closegraph();

  /* Read timer hold registers and figure out how long it took to draw
     circle.  Print results */

  RawCircleTime = 65536*ReadTimerHold(TN_T2) + ReadTimerHold(TN_T1);
  CookedCircleTime = RawCircleTime*F1_RES - overhead;

  printf("Load/Save overhead = %f nanoseconds\n",overhead);
  printf("Raw Circle Counts = %lu\n",RawCircleTime);
  printf("It took %f nanoseconds to draw the circle\n",CookedCircleTime);

}
