/*

This program allows the operator (via the STDIO window in Dynamic C)
to recalibrate the analog input channels. After the recalibration,
the program let the operator to set a minimum change threshold, and
report changes on any analog channels that exceeds the threshold.

*/

#use eziopk25.lib

#define NUMINPUT 4

/*
getFloat gets a floating point number from the STDIO window. If the
operator enters a invalid string, this function displays a message
and prompt the user again.
*/

float getFloat() {
  auto char inputString[256];
  auto int done;
  auto float result;

  done = 0;

  do {													//	keep asking the operator
    inputString[0] = 0;
    while (!getswf(inputString)) hitwd();		//	wait for an input string
    result = atof(inputString);					//	try to interpret it as a float
    if (_xtoxErr) {									//	check if interpretation was ok
		//	if not okay, display a message
      printf("invalid floating number, please reenter\n");
    } else {
    	//	if okay, we are done
      done = 1;
    }
  } while (!done);									//	exit loop when we are done
  return result;										//	return the number just entered
}

/*

getChoice waits for the user to enter 'n', 'N', 'y' and 'Y'. It
returns whether the user selects 'y' or 'Y'.

*/

int getChoice() {
  static char *choices = "nNyY";					//	response characters
  auto int result;

  while (!(result = selectkey(choices))) {
    hitwd();				//	keep inputing until choice is	made
  }
  return result > 2;		//	'y' and 'Y' have indices 3 and 4
}

void main() {
  int i;
  float f1,f2;
  unsigned d1,d2;
  char inputString[256];
  float margin;
  float lastValue[NUMINPUT];
  float thisReading;

  _GLOBAL_INIT();
  eioBrdInit(0);							//	initialize the board first
  printf("Do you want to calibrate the analog inputs?\n");
  if (getChoice()) {
    // if the user wants to calibrate first
    
    for (i = 0; i < NUMINPUT; ++i) {			// for each channel do
      printf("Calibrating channel %d\n",i);	//	indicate the channel #
      printf("Please connect ref. voltage 1 and enter its value: ");
      f1 = getFloat();								//	ask for the analog value
      d1 = _eioBrdAI(i);							//	get the raw reading
      printf("The ADC reports %04x\n",d1);	//	echoes back the raw reading
      printf("Please connect ref. voltage 2 and enter its value: ");
      f2 = getFloat();								//	ask for the second analog value
      d2 = _eioBrdAI(i);							//	get the second raw value
      printf("The ADC reports %04x\n",d2);	//	echoes the raw reading
      eioBrdACalib(i,d1,d2,f1,f2);				//	calibrate
      printf("Calibration for channel %d is complete.\n",i);	//	indicate completion
    }
  }

  //	at this point, we are done with calibration (if requested)
  
  printf("Please enter the margin of change-detection: ");
  margin = getFloat();								//	get the margin of detection
  memset(lastValue,0,sizeof(lastValue));		//	initialize the initial values
  while (1) {											//	do this forever
    for (i = 0; i < NUMINPUT; ++i) {			//	for each channel
      thisReading = eioBrdAI(i);					//	read in the analog value
      if (	(lastValue[i]+margin < thisReading) ||
      		(lastValue[i]-margin > thisReading)) {
        // if the current value is sufficiently different from the previous
        // value, print it
        printf("channel %d now reads %f\n",i,thisReading);
        lastValue[i] = thisReading;				//	update the "last" reading
      }
      hitwd();											//	remember to hit the watchdog!
    }
  }
}