/* Variables and functions used for timing of RoBIOS functions */

#include "myfprintf.h"

const int period = 2000; /* n seconds in hundreds of a second */
const int avgloop = 3; /* run loop n times and take average */

char results[2000];
int index_x = 0;

/*
 * Return the closest larger number with two significant digits.
 */
int
round_number(int count)
{
  int i_ = 1;
  while (count > 100)
    {
      count /= 10;
      i_ *= 10;
    }
  return (count+1)*i_;
}

/* 
 * Find a suitable number of iterations for testing a function, then
 * test it and write the results to file.  
 */
#define do_test(name, params)                      \
{                                                  \
  int count_, start_, now_, ignore_, j_;           \
  double ips = 0;                                  \
  start_ = OSGetCount(); now_ = start_; count_ = 0;\
  while (period > (now_ - start_))                 \
    {                                              \
      ignore_ += (int)name params;                 \
      count_++; now_ = OSGetCount();               \
    }                                              \
  count_ = round_number(count_);                   \
  LCDClear();                                      \
  if (count_ < 10) {                               \
  index_x += sprintf(&results[index_x],"Warning: "     \
              "test iterations = %d\n", count_);   \
  }                                                \
  LCDPrintf("Count = %d\n", count_);                  \
                                                   \
  for (j_ = 0; j_ < avgloop; j_++) {               \
    int stop_, period_, i_;                        \
    start_ = OSGetCount();                         \
    for (i_ = 0; i_ < count_; i_++)                \
      {                                            \
        ignore_ += (int)name params;               \
      }                                            \
    stop_ = OSGetCount();                          \
    period_ = (stop_ - start_);                    \
    ips += 100 * count_ / (double)period_;         \
  }                                                \
  LCDClear();                                      \
  index_x += sprintf(&results[index_x],"%s %.2f\n",    \
    #name #params, ips/avgloop);                   \
  LCDPrintf("%s %.2f\n",#name #params,ips/avgloop);   \
}

/*
 * Initialize:
 * print starting message to display
 * print header information to file
 */

int init_test(char * function_type) 
{
  char *camtype = "";
  int camversion = -1; 

  while (INITERROR == (camversion = CAMInit(NORMAL)))
    OSWait(CAMWAIT);

  switch (camversion) {
  case 16:
    camtype = "with Color Quickcam";
    break;
  case 17:
    camtype = "with Eyecam";
    break;
  default:
    break;
  }

  LCDPrintf("Starting... \n");
  
  return sprintf(results, 
		 "Testing: %s\n"
		 "Name: %s (%d)\n"
		 "Speed: %2.1f Mhz\n"
		 "Version: %s %s\n\n"
		 , function_type
		 , OSMachineName()
		 , OSMachineID()
		 , OSMachineSpeed()/1000000.0
		 , OSVersion()
		 , camtype);
}

/* initialize RS232 interface*/
FILE *init_serial(void)
{
  FILE *serial;
  if(0 != OSInitRS232(SER115200, NONE, SERIAL1)) {
    LCDPrintf("RS232 initialization failed\n");
  }
  
  if (NULL == (serial = fopen(SER1, "rw"))) {
    LCDPrintf ("fopen on serial port failed");
  }
  
  setvbuf(serial, NULL, _IONBF, 0);
  return serial;
}

void end_test(void)
{
  FILE *serial;
  char term = 0x04;
  
  LCDMenu("end", "upl", "upl", "upl");

  AUBeep();
  
  switch (KEYGet()) {
  case KEY1:
    return;
    break;
  case KEY2:
  case KEY3: 
  case KEY4: 
    serial = init_serial();
    myfprintf(serial, results);
    OSSendRS232(&term, SERIAL1); /* send termination character */
    fclose(serial);
    break;
  default:
    break;
  }
}  
