/*************************************************************************e
 * FILE:	io_element_control.cpp
 * DESCRIPTION:	this will be between the io_interfaces and io_elements
 *************************************************************************/

#include "control.h"
#include "vehicle.h"
#include "io_element_control.h"
#include "telemetry.h"
#include "thruster_curves.h"
#include <assert.h>
#include "alarm.h"

/************************************************************************
 * extern C functions, if there is ever a need to use the digital       *
 * channels as inputs rather than outputs, just uncomment digital_out.c *
 * and comment out digital_in.c                                         *
 * NOTE: be careful if removing comments with extern "C", we have used   *
 *       the interfaces as a "better C" C++ to enable namespaces        *
 ************************************************************************/

#ifdef __cplusplus
#endif

#define IO_ELEM		1
#define PRIO_IO_ELEM	1
#define BUTTON			1
#define SLIDE			2
#define SYSTEM_VARIABLES		5


IOElementControl ioElementControl;
extern Vehicle vehicle;

static char result_string[512];

/* used for status checking for piping of the overlay */
int	globalAutoHeadOn = 0;
int	globalAutoDepthOn = 0;
int	globalAutoCruiseOn = 0;
int 	bellypack_value = 0;
int 	detritus_select = 9;	
int 	detritus_interlock = 0;
int 	tool_interlock = 0;
int 	tool_select = 5;
float 	bellypack_port = 0.0;
float 	bellypack_stbd = 0.0;


extern int teleos_enable;
extern int ioElement_busy;
extern float auto_heading_setpoint;
extern float auto_depth_setpoint;
extern float auto_cruise_setpoint;
extern float auto_cruise_lat_setpoint;
extern float teleos_fb_foreaft;
extern float teleos_fb_turns;
extern float teleos_fb_lateral;
extern float teleos_fb_vertical;


/*****************************************************************************
* Constructor - initializes the following:
*						1) Control ports for digital interface
*						2) buttons/slidebar initialization
* Returns:
*
* Modified Last By: 
* Date Modified:
* Modification:
******************************************************************************/

IOElementControl::IOElementControl() throw()
{

   writeControlPort(0);
   writeControlPort(1);
   writeControlPort(2);

   first_but = NULL;
   curr_out = NULL;
   but_ptr = NULL;
   curr_prev = NULL;

   first_slide = NULL;
   slide_ptr = NULL;

   bcount = 0;
   scount = 0;

   Detritus_make(); //Creates 2 elements for the switch inputs 49 and 50
   Tool_make();     //Creates 2 elements for the switch inputs 69 and 70

   subout_make();   //Creates the elements used for monitoring hte sub analog outputs thru the adc baord


}


/*****************************************************************************/

IOElementControl::~IOElementControl() throw()
{
   // should NEVER be called!!!

}


/*****************************************************************************
* Adds the I/O elements into the data base
* Initializes the following:
*						1) All of the elements 
*						2) 
* Returns:
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::pushElement(IOElement element) throw()
{

  int type = element.getIOtype();	// better get this right...

  //cout <<" type is : "<<type<<endl;

   if (inDataBase(element)) {
      //cout << "IOElementControl.c: element already in DB\n";
      //cout << "IOElementControl.c: updating element..... \n";

      switch (type) {
      case topDigIn:

      	delete_output(currDigIn->next_out);
                                            	
   	currDigIn->iotype_ = element.iotype_;
   	currDigIn->element_num_ = element.element_num_;
   	currDigIn->element_name_ = element.element_name_;
   	currDigIn->defaults_ = element.defaults_;	
   	currDigIn->default_level_ = element.default_level_;
   	currDigIn->enable_channel_ = element.enable_channel_;
   	currDigIn->auto_calibrate_enable_ = element.auto_calibrate_enable_;
   	currDigIn->analog_offset_ = element.analog_offset_;
   	currDigIn->analog_gain_ = element.analog_gain_;
   	currDigIn->max_ = element.max_;
   	currDigIn->min_ = element.min_;
   	currDigIn->graphics_.color_ = element.graphics_.color_;
   	currDigIn->next_out = NULL;
        	currDigIn->graphics_.vga_screen_ = element.graphics_.vga_screen_;
      	

      	 if (element.graphics_.vga_screen_ == 1)
      	 {
      		currDigIn->graphics_.type_ = element.graphics_.type_;
      		currDigIn->graphics_.x_ = element.graphics_.x_;
      		currDigIn->graphics_.y_ = element.graphics_.y_;      	                                                                 	
      	 	
      	 }
      	 else
      	 {
      	 	currDigIn->graphics_.type2_ = element.graphics_.type_;
      		currDigIn->graphics_.x2_ = element.graphics_.x_;
      		currDigIn->graphics_.y2_ = element.graphics_.y_;      	                                                                 	
      	    	
      	 }
      	
         //topdigitalInList.erase(currDigIn);
	 break;

      case subDigIn:
         	delete_output(currSubDigIn->next_out);
                   	                                                             	
   	currSubDigIn->iotype_ = element.iotype_;
   	currSubDigIn->element_num_ = element.element_num_;
   	currSubDigIn->element_name_ = element.element_name_;
   	currSubDigIn->defaults_ = element.defaults_;	
   	currSubDigIn->default_level_ = element.default_level_;
   	currSubDigIn->enable_channel_ = element.enable_channel_;
   	currSubDigIn->auto_calibrate_enable_ = element.auto_calibrate_enable_;
   	currSubDigIn->analog_offset_ = element.analog_offset_;
   	currSubDigIn->analog_gain_ = element.analog_gain_;
   	currSubDigIn->max_ = element.max_;
   	currSubDigIn->min_ = element.min_;
   	currSubDigIn->graphics_.color_ = element.graphics_.color_;
   	currSubDigIn->next_out = NULL;
        	currSubDigIn->graphics_.vga_screen_ = element.graphics_.vga_screen_;
      	
      	 if (element.graphics_.vga_screen_ == 1)
      	 {
      		currSubDigIn->graphics_.type_ = element.graphics_.type_;
      		currSubDigIn->graphics_.x_ = element.graphics_.x_;
      		currSubDigIn->graphics_.y_ = element.graphics_.y_;      	                                                                 	
      	 	
      	 }
      	 else
      	 {
      	 	currSubDigIn->graphics_.type2_ = element.graphics_.type_;
      		currSubDigIn->graphics_.x2_ = element.graphics_.x_;
      		currSubDigIn->graphics_.y2_ = element.graphics_.y_;      	                                                                 	
      	    	
      	 }

         break;

      case topAnalogIn:
         delete_output(currAnaIn->next_out);

        	currAnaIn->iotype_ = element.iotype_;
   	currAnaIn->element_num_ = element.element_num_;
   	currAnaIn->element_name_ = element.element_name_;
   	currAnaIn->defaults_ = element.defaults_;	
   	currAnaIn->default_level_ = element.default_level_;
   	currAnaIn->enable_channel_ = element.enable_channel_;
   	currAnaIn->auto_calibrate_enable_ = element.auto_calibrate_enable_;
   	currAnaIn->analog_offset_ = element.analog_offset_;
   	currAnaIn->analog_gain_ = element.analog_gain_;
   	currAnaIn->max_ = element.max_;
   	currAnaIn->min_ = element.min_;
   	currAnaIn->graphics_.color_ = element.graphics_.color_;
   	currAnaIn->next_out = NULL;
   	currAnaIn->graphics_.vga_screen_ = element.graphics_.vga_screen_;
      	
      	 if (element.graphics_.vga_screen_ == 1)
      	 {
      		currAnaIn->graphics_.type_ = element.graphics_.type_;
      		currAnaIn->graphics_.x_ = element.graphics_.x_;
      		currAnaIn->graphics_.y_ = element.graphics_.y_;      	                                                                 	
      	 	
      	 }
      	 else
      	 {
      	 	currAnaIn->graphics_.type2_ = element.graphics_.type2_;
      		currAnaIn->graphics_.x2_ = element.graphics_.x2_;
      		currAnaIn->graphics_.y2_ = element.graphics_.y2_;      	                                                                 	
      	    	
      	 }
      	
	 break;
      case subAnalogIn:
        delete_output(currSubAnaIn->next_out);
      	
      	                                                             	
   	currSubAnaIn->iotype_ = element.iotype_;
   	currSubAnaIn->element_num_ = element.element_num_;
   	currSubAnaIn->element_name_ = element.element_name_;
   	currSubAnaIn->defaults_ = element.defaults_;	
   	currSubAnaIn->default_level_ = element.default_level_;
   	currSubAnaIn->enable_channel_ = element.enable_channel_;
   	currSubAnaIn->auto_calibrate_enable_ = element.auto_calibrate_enable_;
   	currSubAnaIn->analog_offset_ = element.analog_offset_;
   	currSubAnaIn->analog_gain_ = element.analog_gain_;
   	currSubAnaIn->max_ = element.max_;
   	currSubAnaIn->min_ = element.min_;
   	currSubAnaIn->graphics_.color_ = element.graphics_.color_;
   	currSubAnaIn->next_out = NULL;
   	currSubAnaIn->graphics_.vga_screen_ = element.graphics_.vga_screen_;
      	   	      	                  	                                            	
      	 if (element.graphics_.vga_screen_ == 1)
      	 {                                                  	
      		currSubAnaIn->graphics_.type_ = element.graphics_.type_;
      		currSubAnaIn->graphics_.x_ = element.graphics_.x_;
      		currSubAnaIn->graphics_.y_ = element.graphics_.y_;
      	 }
      	
      	 if (element.graphics_.vga_screen_ == 2)      	
      	 {
      	 	currSubAnaIn->graphics_.type2_ = element.graphics_.type2_;
      		currSubAnaIn->graphics_.x2_ = element.graphics_.x2_;
      		currSubAnaIn->graphics_.y2_ = element.graphics_.y2_;      	                                                                 	      		
      	 }                                                            	
   	
      	
       //  subanalogInList.erase(currSubAnaIn);

         break;

      case topAnalogOut:

      	// NOTE : do not set the out_string to be null  here because when we press
      	// OK, we will set it to be null here.
      	// When we press "OK" From the GUI command "ok_command"
      	// inside file "out_elem_prop.tcl" we do not resend the inputl ist info again.
      	// So if we clear  the out_string here, we will always end up with
      	// empty list for the input listbox in the GUI
      	
         	//currAnaOut->out_string = "\0";

         	
       	currAnaOut->iotype_ = element.iotype_;
   	currAnaOut->element_num_ = element.element_num_;
   	currAnaOut->element_name_ = element.element_name_;
   	//currAnaOut->defaults_ = element.defaults_;	
   	//currAnaOut->default_level_ = element.default_level_;
   	//currAnaOut->enable_channel_ = element.enable_channel_;
   	//currAnaOut->auto_calibrate_enable_ = element.auto_calibrate_enable_;
   	currAnaOut->analog_offset_ = element.analog_offset_;
   	currAnaOut->analog_gain_ = element.analog_gain_;
   	currAnaOut->max_ = element.max_;
   	currAnaOut->min_ = element.min_;
   	//currAnaOut->graphics_.color_ = element.graphics_.color_;
   	//currAnaOut->next_out = NULL;
   	//currAnaOut->graphics_.vga_screen_ = element.graphics_.vga_screen_;

        //cout <<"io_element_control.cpp : updating the anaout elem num : "<<currAnaOut->element_num_<<endl;
        //cout <<"io_element_control.cpp : updating the analog gain : "<<currAnaOut->analog_gain_<<endl;

             break;


      default:
         return false;
      }

   }

    // cout << "IOElementControl.c: adding element in DB \n";

    else {

     switch (type) {
      case topDigIn:
        topdigitalInList.push_back(element);
 	 break;
      case subDigIn:
          subdigitalInList.push_back(element);
         break;
      case topAnalogIn:
	 topanalogInList.push_back(element);
         break;
      case subAnalogIn:
         subanalogInList.push_back(element);
         break;
      case topAnalogOut:
	topanalogOutList.push_back(element);
	//cout <<"io_element_control.cpp : pushing analog out element the first time \n";
  	break;
      default:
         return false;
      }

  }
   return true;

}


/*****************************************************************************
* Called to get the element particulars.  Needs 3 parameters, surf or sub,
* dig or ana, and element number.
* Initializes the following:
*						1) 
*						2) 
* Returns:  The pointer to the element, but does not change the data base pointer.
*		To change the data base pointer see function below. Same name different
*		parameters passed. (poly morphic function)
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

digIterator
IOElementControl::getIOElement(int surfVehicle, int digAnalog,
                               int element_num, 
			       digIterator it) throw()
{
  int type = findIOtype(surfVehicle, digAnalog);

  int i;

   switch(type) {
	case topDigIn:
	   for(i = 0; i < topdigitalInList.size(); i++) {
	      if (topdigitalInList[i].num() == element_num) {
		 it =  &topdigitalInList[i];
		 return it;
	      }
	   }
	   break;
        case subDigIn:
           for(i = 0; i < subdigitalInList.size(); i++) {
	      if (subdigitalInList[i].num() == element_num) {
	         it =  &subdigitalInList[i];
		 return it;
	      }
	   }
           break;
        case topAnalogIn:
           for(i = 0; i < topanalogInList.size(); i++) {
	      if (topanalogInList[i].num() == element_num) {	
		 it = &topanalogInList[i];
		 return it;
	      }
	   }
           break;
	case subAnalogIn:
           for(i = 0; i < subanalogInList.size(); i++) {
	      if (subanalogInList[i].num() == element_num) {
		 it = &subanalogInList[i];
		 return it;
	      }
	   }
           break;

        case topAnalogOut:
           for(i = 0; i < topanalogOutList.size(); i++) {
	      if (topanalogOutList[i].num() == element_num) {	
		 it = &topanalogOutList[i];
		 return it;
	      }
	   }
           break;
 
  }

   return NULL;

}

/*****************************************************************************
* Changes the pointer in the data base to the element passed to it.
* Initializes the following: 
*						1) the element data base pointer 
*						2) 
* Returns: the type of element ie: surf or sub, analog or digital, input or output
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::getIOElement(int surfVehicle, int digAnalog,
                               int element_num) throw()
{
  int type = findIOtype(surfVehicle, digAnalog);

  //cout << "IOElementControl: type: " << type << endl;

  int i;

   switch(type) {
	case topDigIn:
	   for(i = 0; i < topdigitalInList.size(); i++) {
	      if (topdigitalInList[i].num() == element_num) {
		 currDigIn = &topdigitalInList[i];
		 //cout << "IOElementControl.c: getIOElement()\n";
	         return type;
	      }
	   }
	   break;
        case subDigIn:
           for(i = 0; i < subdigitalInList.size(); i++) {
	      if (subdigitalInList[i].num() == element_num) {
	         currSubDigIn = &subdigitalInList[i];
		 return type;
	      }
	   }
           break;
        case topAnalogIn:
           for(i = 0; i < topanalogInList.size(); i++) {
	      if (topanalogInList[i].num() == element_num) {	
		 currAnaIn = &topanalogInList[i];
	         return type;
	      }
	   }
           break;
	case subAnalogIn:
           for(i = 0; i < subanalogInList.size(); i++) {
	      if (subanalogInList[i].num() == element_num) {
		 currSubAnaIn = &subanalogInList[i];
	         return type;
	      }
	   }
           break;

            case topAnalogOut:
           for(i = 0; i < topanalogOutList.size(); i++) {
	      if (topanalogOutList[i].num() == element_num) {	
		 currAnaOut = &topanalogOutList[i];
	         return type;
	      }
	   }
           break;
   }

   return -1;

}

/*****************************************************************************
* Displays the switch status on the BPM from the element data base.  Not from the driver.
* Passed the element parameters and checks that the element asked for 
* is a surface digital input.
* Initializes the following:
*						1)  
*						2) 
* Returns: the value of the digital input
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int IOElementControl::readFromChannel(int surfVehicle, int digAnalog,
                                  int element_num) throw()
{
   /* surfVehicle: 	0 - vehicle
    * 		   	1 - surface
    * digitalAnalog:	0 - Analog
    * 		        1 - digital
    */
	/* NEED TO IMPLEMENT ALARMS */
	
   int result;

	if (getIOElement(surfVehicle, digAnalog, element_num) != topDigIn) return -1;
      	currDigIn->digital_value_ = !topDigitalChannel[element_num];
      	return currDigIn->digital_value_;
}


/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* elem_prop.tcl
* 
* Initializes the following:
*						1) 
*						2) 
* Returns: True if element is there. False if that element does not exist
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool IOElementControl::retIOString(int surfVehicle, int digAnalog, int element_num, int screen, char retString[]) throw()
{  	
   int type = getIOElement(surfVehicle, digAnalog, element_num);

   switch (type)
   {
   	case topDigIn:
   	        readFromChannel(surfVehicle, digAnalog, element_num);
  		currDigIn->getAllInfo(surfVehicle, digAnalog, element_num, screen, retString);
                return true;

        case subDigIn:
        	currSubDigIn->getAllInfo(surfVehicle, digAnalog, element_num, screen, retString);
        	return true;

        case topAnalogIn:
   	        currAnaIn->getAllInfo(surfVehicle, digAnalog, element_num, screen, retString);
                return true;

        case subAnalogIn:
        	currSubAnaIn->getAllInfo(surfVehicle, digAnalog, element_num, screen, retString);
        	return true;

        case topAnalogOut:
                currAnaOut->getAllInfo(surfVehicle, digAnalog, element_num, screen, retString);
	        //cout <<"retString is : "<<retString<<endl;
	        return true;
   	}
      	sprintf(retString, "%d", -1);
      	return false;
}


/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* configuration.cpp.  Different from above in that the index only is passed.
* We know type so we don't need to pass it.
* Initializes the following:
*						1) 
*						2) 
* Returns:
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool IOElementControl::retDigitalObjString(char objString[], int index) throw()
{
   if (index >= topdigitalInList.size())
   	{
       	//cout << "IOElementControl.c: Error: index out of range\n";
       	return false;
   	}
   topdigitalInList[index].getAllInfo(objString);
   return true;
}


/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* configuration.cpp.  Different from above in that the index only is passed.
* We know type so we don't need to pass it.
* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::retAnalogObjString(char objString[], int index) throw()
{

   if (index >= topanalogInList.size()) {
       //cout << "IOElementControl.c: Error: index out of range\n";
       return false;
   }

   topanalogInList[index].getAllInfo(objString);
   return true;

}


/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* configuration.cpp.  Different from above in that the index only is passed.
* We know type so we don't need to pass it.* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::retSubDigitalObjString(char objString[], int index) throw()
{

   if (index >= subdigitalInList.size()) {
       //cout << "IOElementControl.c: Error: index out of range\n";
       return false;
   }

   subdigitalInList[index].getAllInfo(objString);
   return true;

}




/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* configuration.cpp.  Different from above in that the index only is passed.
* We know type so we don't need to pass it.* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::retSubAnalogObjString(char objString[], int index) throw()
{

   if (index >= subanalogInList.size()) {
       //cout << "IOElementControl.c: Error: index out of range\n";
       return false;
   }

   subanalogInList[index].getAllInfo(objString);

   return true;

}



/*****************************************************************************
* Fetches all the parameters of the element passed in.  Called by 
* configuration.cpp.  Different from above in that the index only is passed.
* We know type so we don't need to pass it.* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/


bool
IOElementControl::retTopAnalogOutObjString(char objString[], int index) throw()
{


   if (index >= topanalogOutList.size()) {
       //cout << "IOElementControl.c: Error: index out of range\n";
       return false;
   }

   topanalogOutList[index].getAllInfo(objString);
   return true;

}



/*****************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::retDigSize()
{
   return(topdigitalInList.size());
}


/*****************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::retAnaSize()
{
   return(topanalogInList.size());
}

/*****************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::retSubDigSize()
{
   return(subdigitalInList.size());
}


/*****************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::retSubAnaSize()
{
   return(subanalogInList.size());
}

/*****************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::retAnaOutSize()
{
   return(topanalogOutList.size());
}

/*****************************************************************************
* The polling function loads the varius analog arrays.  Then this function
* applies the gains and offsets, max and min values to the float pointer passed in.
* Does the arithmetic from raw to the usable analog value. 
* Initializes the following: 
*						1) 
*						2) 
* Returns: Loads the float pointer passed in with the calculated analog value.
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::readVoltage(int surfVehicle, int digAnalog,
                              int element_num, float& analog,
                              float& raw, float& gain, float& offset,
			      float& max, float& min) throw()
{
   /* surfVehicle: 	0 - vehicle
    * 		   	1 - surface
    * digitalAnalog:	0 - Analog
    * 			1 - digital
    * 			3 - analog output
    */
 
   int res;
   int type;
   float voltage;
   
   type = getIOElement(surfVehicle, digAnalog, element_num);
   //cout << "ioElementControl: type is: " << type << endl;
   
   switch(type) {
	case topAnalogIn:
		assert(currAnaIn);
		if (!currAnaIn->isChannelenabled())
		{
			//cout << "ioElementControl: channel disabled\n";
			return false;
		}
		
		else
		{
			//readVolt(ioFD, element_num, voltage, raw);
			voltage = current_adc[element_num - 1].volt;
			raw = current_adc[element_num - 1].intVolt;	
			gain = currAnaIn->analog_gain_;
			offset = currAnaIn->analog_offset_;
			currAnaIn->analog_value_ = (voltage * gain) + offset ;
  			currAnaIn->analog_raw_ = voltage;
			
			analog = currAnaIn->analog_value_;
			raw = currAnaIn->analog_raw_;
			max = currAnaIn->max_;
			min = currAnaIn->min_;
			
			return true;
		}
		
	
	case subAnalogIn:
		assert(currSubAnaIn);
		
		raw = currSubAnaIn->analog_raw_;
		gain = currSubAnaIn->analog_gain_;
		offset = currSubAnaIn->analog_offset_;
		max = currSubAnaIn->max_;
		min = currSubAnaIn->min_;
		analog = gain*raw + offset;
		
		return true;
		
	case topAnalogOut:      
		assert(currAnaOut);
			anaIterator iterator ;
   			int input_type, elnum;

                        // variables that are going to be returned / displayed
   			gain = currAnaOut->analog_gain_;
			offset = currAnaOut->analog_offset_;
			max = currAnaOut->max_;
			min = currAnaOut->min_;
	
			
                        if ( currAnaOut->next_out != NULL )
      			{
                                // get the input element data : surface or sub, analog ( 0 ), and element number

         			input_type = currAnaOut->next_out->out_board;
			        elnum = currAnaOut->next_out->out_elem_num;

			        //cout <<"io_element_control.cpp: top analog out input : "<<input_type<<" "<<elnum<<endl;
			
			        if (input_type == SYSTEM_VARIABLES) 	// System Variables
			        {
			        	switch (elnum)
			        	{
			        		case 1:   		// Heading
			        			raw = vehicle.curr_heading;
			        			//cout <<"raw head : "<<raw<<endl;
			        			break;
			        		case 2:         	// Depth
			        		        raw = vehicle.curr_depth;  	
			        			//cout <<"raw depth : "<<raw<<endl;			        			
			        			break;
			        		case 3:      	// Pitch
			        		        raw = vehicle.curr_pitch;
			        			//cout <<"raw pitch : "<<raw<<endl;			        			
			        			break;
			        		case 4:       	// Roll
			        			raw = vehicle.curr_roll;
			        			//cout <<"raw roll : "<<raw<<endl;			        			
			        			break;
			        		default:
			        			break;
			        		      			        	
			        	
			        	}	// end switch case    	 	
			             	
			        	//-----------------------------------------------------------------				
			   		// Get the analog value after applying the gain and offset to raw value
			   		//-----------------------------------------------------------------			
						
			   		//cout <<"gain : "<<gain<<endl;
					//cout <<"elnum : "<<offset<<endl;
				        			   	
			   		analog = raw*gain + offset;  //Only done if the data is from a serial string
			   			
			   				
			        }      	// end if (input_type == 5)
			             	
			        else        // input_type == 0 ( sub analog in )
			        {
			             	
			             	//-----------------------------------------------------------------			
					// set the "out_iterator" to point to the element where the input is coming from
					// in order to get the CALCULATED ANALOG as the RAW VALUE of of our analog element
					// Note : Analog = 0 -> for the second parameter
					//-----------------------------------------------------------------			
								
					if ((iterator = getIOElement(input_type, 0, elnum, iterator)) != NULL );
				        {							
						
				        	//cout <<"input_type : "<<input_type<<endl;
				        	//cout <<"elnum : "<<elnum<<endl;
				        	
						raw =  (iterator->analog_raw_ * iterator->analog_gain_) + iterator->analog_offset_;
			        		//cout <<"input value : "<<raw<<endl;
						
			        		//-----------------------------------------------------------------				
			   			// Get the analog value after applying the gain and offset to raw value
			   			//-----------------------------------------------------------------			
						
			   			//cout <<"input gain : "<<iterator->analog_gain_<<endl;
						//cout <<"input offset: "<<iterator->analog_offset_<<endl;
				        			   	
			   			analog = raw*gain + offset;
			   			
			        		return true;
			        		
			   		}	
			   		
			   	}	// end else
			   	
			
			   	
			   		
			} 	// end if  (currOut->next_out != NULL)
			
			else 	// if there is not input for this analog output (currOut->next_out == NULL)
			{
				raw = 0;
				analog = 0;
				
      			}
				
			
		return true;          		
	
	default:
		//cout << "ioELementControl: type mismatch\n";
		return false;
		
 	}

}


/*****************************************************************************
* Checks the element data base for the existance of the element passed in.
* used to  make sure the is not a duplicate element created.
* Initializes the following:
*						1) 
*						2) 
* Returns: True if the element exists, false if its ok to create the element
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

bool
IOElementControl::inDataBase(IOElement element)
{
  int type = element.getIOtype();
  int i;

   switch(type) {
	case topDigIn:
	   for(currDigIn = topdigitalInList.begin();
               currDigIn != topdigitalInList.end(); ++currDigIn) {
	      if (currDigIn->num() == element.num()) {	
	         //cout << "IOElementControl.c: inDataBase\n";
                 //currDigIn->test();
                 return true;
              }
	   }
           break;	
        case subDigIn:
           for(currSubDigIn = subdigitalInList.begin();
               currSubDigIn != subdigitalInList.end(); ++currSubDigIn) {
	      if (currSubDigIn->num() == element.num()) {	
	         //cout << "IOElementControl.c: inDataBase\n";
                 //currSubDigIn->test();
                 return true;
              }
	   }
           break;
        case topAnalogIn:
           for(currAnaIn = topanalogInList.begin();
               currAnaIn != topanalogInList.end(); ++currAnaIn) {
	      if (currAnaIn->num() == element.num()) {	
	         //cout << "IOElementControl.c: inDataBase\n";
                 //currAnaIn->test();
	         return true;
              }
	   }
           break;
	case subAnalogIn:
           for(currSubAnaIn = subanalogInList.begin();
               currSubAnaIn != subanalogInList.end(); ++currSubAnaIn) {
	      if (currSubAnaIn->num() == element.num()) {	
                 //cout << "IOElementControl.c: in DataBase\n";
                 //currSubAnaIn->test();
	         return true;
              }
	    }
            break;

        case topAnalogOut:
           for(currAnaOut = topanalogOutList.begin();
               currAnaOut != topanalogOutList.end(); ++currAnaOut) {
	      if (currAnaOut->num() == element.num()) {	
	         //cout << "IOElementControl.c: inDataBase\n";
                 //currAnaOut->test();
	         return true;
              }
	   }
           break;
   }

   return false;


}


/*****************************************************************************
* Erases the current data base before you open another config file.
* Initializes the following:
*						1) the data base to null
*						2) 
* Returns: none
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

void
IOElementControl::clean_db()
{

       topdigitalInList.erase(topdigitalInList.begin(), topdigitalInList.end());
       subdigitalInList.erase(subdigitalInList.begin(), subdigitalInList.end());
       topanalogInList.erase(topanalogInList.begin(), topanalogInList.end());
       subanalogInList.erase(subanalogInList.begin(), subanalogInList.end());
       topanalogOutList.erase(topanalogOutList.begin(), topanalogOutList.end());


      return;
}

/*****************************************************************************
* dumps the data base onto the screen or a temporary file for developement
* not called normally
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

void
IOElementControl::dump()
{
   cout << "\n++++++++++++++++++++++ DATABASE DUMP ++++++++++++++++++++++\n";
   cout << "\nTOP Digital In Elements: \n";
   cout << "======================\n";
   cout << "size: " << topdigitalInList.size() << "\n";
  // cout << "capacity: " << topdigitalInList.capacity() << "\n";
   for (int i = 0; i < topdigitalInList.size(); i++)
      topdigitalInList[i].test();

   cout << "\nSUB Digital In Elements: \n";
   cout << "======================\n";
   cout << "size: " << subdigitalInList.size() << "\n";
  // cout << "capacity: " << subdigitalInList.capacity() << "\n";
   for (int i = 0; i < subdigitalInList.size(); i++)
      subdigitalInList[i].test();

   cout << "\nTOP Analog In Elements: \n";
   cout << "======================\n";
   cout << "size: " << topanalogInList.size() << "\n";
 //  cout << "capacity: " << topanalogInList.capacity() << "\n";
   for (int i = 0; i < topanalogInList.size(); i++)
      topanalogInList[i].test();

   cout << "\nSUB Analog In Elements: \n";
   cout << "======================\n";
   cout << "size: " << subanalogInList.size() << "\n";
//   cout << "capacity: " << subanalogInList.capacity() << "\n";
   for (int i = 0; i < subanalogInList.size(); i++)
      subanalogInList[i].test();

    cout << "++++++++++++++++++++ DATABASE DUMP END ++++++++++++++++++\n";

    dump_output();
}

/*****************************************************************************
* dump to the screen the outputs connected to the element.
* not called normally.
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

void
IOElementControl::dump_output()
{

   cout << "\n++++++++++++++++++++++ DUMP OUTPUT ++++++++++++++++++++++\n\n";
   cout << "\nTOP Digital In Elements: \n";
   cout << "======================\n";
   cout << "size: " << topdigitalInList.size() << "\n";
   test_output(topDigIn);


   cout << "\nSUB Digital In Elements: \n";
   cout << "======================\n";
   cout << "size: " << subdigitalInList.size() << "\n";
   test_output(subDigIn);

   cout << "\nTOP Analog In Elements: \n";
   cout << "======================\n";
   cout << "size: " << topanalogInList.size() << "\n";
   test_output(topAnalogIn);

   cout << "\nSUB Analog In Elements: \n";
   cout << "======================\n";
   cout << "size: " << subanalogInList.size() << "\n";
   test_output(subAnalogIn);



   cout << "\nTOP Analog Out Elements: \n";
   cout << "======================\n";
   cout << "size: " << topanalogOutList.size() << "\n";
   test_output(topAnalogOut);

    cout << "++++++++++++++++++++ OUTPUT DUMP END ++++++++++++++++++\n\n";

}

/*****************************************************************************
* Indicates if the element is analog or digital.
* Initializes the following:
*						1) 
*						2) 
* Returns: the element type
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int 
findIOtype(int surfVehicle, int digAnalog)
{
   int iotype = -1;

   if (surfVehicle == 0) {
	// vehicle - sub
	switch (digAnalog) {
		case 0:
			iotype = subAnalogIn;
			break;
		case 1:
			iotype = subDigIn;	
			break;
	}
   }

   else //(surfVehicle == 1) {
   {
	// surface - top
	switch (digAnalog) {
		case 0:
			iotype = topAnalogIn;
			break;
		case 1:
			iotype = topDigIn;	
			break;
                case 3:
			iotype = topAnalogOut;
		             //cout <<"io_element_control.coo: better find the type here heh \n";
		             break;
	}

   }

   return iotype;

}


/*****************************************************************************
* Accepts the element and a string that holds the outputs that are connected
* to the element.  Parses the string and then creates a node(s) which the element
* is connected to. An input element can have multiple nodes and the
* output elements can only have one node.
* Basically this functions connects the selected outputs to the desired inputs.
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
void IOElementControl::make_input_output(int surfVehicle, int digAnalog, int element_num, char some_string[])
{
      	string str(some_string);
	//cout<<"--------------STRING IS "<<str<<endl;
	// ------------- parse the output string ---------------------
       	
       	char *ptr;
	int type;		// type returned
   	int count = 0;
	string temp[100]; // max number of output info

      	ptr = strtok(some_string, "|" );
      	while (ptr)
      	{
         	//cout << ptr << " ";
         	temp[count] = ptr;
         	count++;
         	ptr = strtok(NULL, "|" );
      	}
      	//cout <<"\n";

      	output_count = count /2;
      	Output_List *tempOut = NULL;
	curr_out = NULL;     	// declared in "io_element_control.h"
      	
      	type = getIOElement( surfVehicle, digAnalog, element_num); 	// get the correct pointer curr***

        //cout <<"surfVehicle, digAnalog, element_num, argv[4] = "<<surfVehicle<<" "<<digAnalog<<" "<<element_num<<" "<<str<<endl;
            	
      	if (surfVehicle == 1)	// surface input
    	{
           // this is to check if there is no output node left at all

           if (digAnalog == 1 && currDigIn != NULL)
 		currDigIn->out_string = str;
    	   	
           if (digAnalog == 0 && currAnaIn != NULL)				
           	currAnaIn->out_string = str;
	
 	   for ( int i = 0; i+2 <= count; i=i+2 )
	   {
        	//----------------- make a new node ----------------------------
      		Output_List *out = new Output_List;
		out->next = NULL;
	   	out->out_surveh = 1;  			// bottom output
	   	out->out_diganal = -1;   		// not needed -> set to -1	             	
		out->out_elem_num = atoi(temp[i+1].c_str());
    	 	out->out_board = atoi(temp[i].c_str());	
    	    	
    	        // get the digital value
    	        //out->out_digital_value = -1;                 	
    	        out->out_digital_value = readFromChannel(surfVehicle, digAnalog, element_num);
                out->out_digital_value = 1;                                                    	
   	   		
   		//if (out->out_digital_value == 1) cout << "io_element_control.cpp : digital channel read 1.";
   		//else if ( out->out_digital_value == 0) cout << "io_element_control.cpp : digital channel read 0.";
   		//else cout << "io_element_control.cpp : digital channel undefined.";
       		
   		if(digAnalog == 1)
   		{
   		       /*----------------------------------------------------------------------------
   		 	* NOTE  :
   		 	* "tempOut" is the pointer that keeps on adding the output at the end
   		 	* of the output list nodes
   		 	* "curr_out" is the pointer that traverse the output list nodes each time
   		 	* starting from "currDigIn->next_out to the end of output list
   		 	* "out" is a pointer to the new created node   		
   		 	----------------------------------------------------------------------------*/
   		
    			tempOut = currDigIn->next_out;
                          			
			// first node
			if (tempOut == NULL)
			{
				//cout <<"io_element_control : There is nothing in the output list"<<endl;
				currDigIn->next_out = out;	
    			}
			else
			{
		   		// when there are more than one node		
		   		// digital - traverse the existing list
	  	   		for(curr_out = currDigIn->next_out; curr_out != NULL; curr_out = curr_out->next)
	  	   		{
		      			tempOut = curr_out;
		   	     	}
		   	     	
		   		tempOut->next = out;
		
			} 	// end else
			
			// Might not need this because we have already done this checking above
			// attach the output string "|board#|elem#|board#|elem#|..."
			if (currDigIn != NULL)
				currDigIn->out_string = str;
    	   	
    	   	
    	   	}  	// end if (digAnalog == 1)
    	   	    	   	
    	   	else if (digAnalog == 0)	// if it is Surface Analog Input
    	   	{
    	   	    	tempOut = currAnaIn->next_out;
                          			
			// first node
			if (tempOut == NULL)
				currAnaIn->next_out = out;	

			else
			{       			
		   		// when there are more than one node		
		   		// analog - traverse the existing list
	  	   		for(curr_out = currAnaIn->next_out; curr_out != NULL; curr_out = curr_out->next)
	  	   		{
		      			tempOut = curr_out;
		   	     	}
		   	     	
		   		tempOut->next = out;
		
			} 	// end else           	   	
    	   	
			// Might not need this checking here, because we have already moved it up
			if (currAnaIn != NULL)
				currAnaIn->out_string = str;

    	   	}	// end else (digAnalog == 0)	
    	   	
   	
    	   		
      		//-----------------------------------------------------------
      		//
      		// surfVehicle = 1 -> Surface Channel
      		// digAnalog = 3  -> Analog Out type
      		//
      		//And every analog out channel can only be
      		// associated with one input. Therefore we do not need to create a link list
      		// in other word, we do not need to create a node for that. We are just
      		// going to manipulate the string "out_string" to contain the input information
      		// "out_string" will be in format  "surveh|elem_num|" ,
      		// surveh = 1 	if input is from surface and vice versa
      		// elem_num 	which channel from surface/sub it is
      		//
      		//-----------------------------------------------------------
      	    	   	
    	   	else       // digAnalog == 3 -> it is actually an INPUT for Analog Output channel, not output
    	   	{
  			
    	   		// delete the old one and update it with the current one
    	   		// Note : we do not have to do traversal like above because in this case
    	   		// we can only have one input node for an output node.
    	   		// It is One - to - One mapping
    	   		
    	   	   	
    	   		if ( (currAnaOut->next_out != NULL) || (strlen(str.c_str()) == 0) )
    	   			delete_single_input (element_num);
    	   			
    	   		else
    	   		{	
    	   			
    	   			currAnaOut->next_out = out;    	   		
    	   			  				currAnaOut->out_string = str;
  			}

    	   	}	// end else (digAnalog == 3)	
   		
    	   	
    	   	
    	   	
   	   } // end for ()           	
   	
 	} // end if (surfVehicle == 1)
 	
 	
       	/*------------------------------------------------------------------------------------------
       	 * NOTE :
       	 * In here, we only have ONE output nodes, because the output for the surface is going to
       	 * be a graphic only, so here we only create ONE node that keep the digital,
       	 * analog, and raw analog value only.
       	 ------------------------------------------------------------------------------------------*/
       	        	
 	else 	// surfVehicle == 0 -> vehicle input
 	{
 		Output_List *out = new Output_List;
 		out->next = NULL;                        		
 		 		
 		out->out_surveh = 0;			// output surface
 		out->out_diganal = digAnalog;
 		out->out_elem_num = element_num;
 		out->out_board = -1;			// not needed -> set to -1
 		
 		// for now -> but it should get it from the bottom tho
 		out->out_digital_value = 1;
 		out->out_analog_value = 1;
 		out->out_analog_raw = 1;
 		
 		// get the digital and analog value from the bottom using these functions get_***
 	
 		if (digAnalog == 1) 			// Vehicle digital
 		{	
 			currSubDigIn->next_out = out;
 		 	currSubDigIn->out_string = str;
 		}
 		else              			// Vehicle analog
 		{
 			currSubAnaIn->next_out = out;
 			currSubAnaIn->out_string = str;
 		}
 	 						
 	}     	// end else

 	//dump_output();
 	return;
 	
}

/*****************************************************************************
* Called by test_output 
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

void
IOElementControl::test_output_helper(Output_List *curr)
{
	if (curr != NULL)
        {
        	//cout<<"output size : \n";                      	
   		cout<<"test: out_surveh : "<<curr->out_surveh<<endl;
   		cout<<"test: out_diganal : "<<curr->out_diganal<<endl;
   		cout<<"test: out_elem_num : "<<curr->out_elem_num<<endl;
   		cout<<"test: out_board : "<<curr->out_board<<endl;
   		cout<<"test: out_digital_value : "<<curr->out_digital_value<<endl;
   		cout<<"test: out_analog_value : "<<curr->out_analog_value<<endl;
   		cout<<"test: out_analog_raw : "<<curr->out_analog_raw<<endl;
   	
        }
}


/*****************************************************************************
* Called by dump output.  Finds the output connected to the element. or outputs.
* Calls test_output_dump and displays the output.
* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

void
IOElementControl::test_output(int type)
{

   // topDigIn	
   if (type == topDigIn)
   {
      for(currDigIn = topdigitalInList.begin(); currDigIn != topdigitalInList.end(); ++currDigIn)
      {	

         for (curr_out = currDigIn->next_out; curr_out != NULL; curr_out = curr_out->next)
         {
         	
		test_output_helper(curr_out);
         	//cout<<"------------- next topDigIn ioElement --------------- \n";
         }                                                         	                          		
   	//cout <<"currDigIn is NULL \n";	
      }
   }

  	 	
   // subDigIn	
   if (type == subDigIn)
   {
      for(currSubDigIn = subdigitalInList.begin(); currSubDigIn != subdigitalInList.end(); ++currSubDigIn)
      {	
         for (curr_out = currSubDigIn->next_out; curr_out != NULL; curr_out = curr_out->next)
         {
         	
		test_output_helper(curr_out);
         	//cout<<"------------- next subDigIn ioElement --------------- \n";
         }                                                         	                          		
   	//cout <<"currSubDigIn is NULL \n";	

      }

    }

	
   // topAnalogIn	
   if (type == topAnalogIn)
   {
      for(currAnaIn = topanalogInList.begin(); currAnaIn != topanalogInList.end(); ++currAnaIn)
      {	
         for (curr_out = currAnaIn->next_out; curr_out != NULL; curr_out = curr_out->next)
         {
         	
		test_output_helper(curr_out);
         	//cout<<"------------- next topAnaIn ioElement --------------- \n";
         }                                                         	                          		
   	 //cout <<"currAnaIn is NULL \n";	

      }    	

   }
	 	 	
   // subAnalogIn	
   if (type == subAnalogIn)
   {
      for(currSubAnaIn = subanalogInList.begin(); currSubAnaIn != subanalogInList.end(); ++currSubAnaIn)
      {           	
         for (curr_out = currSubAnaIn->next_out; curr_out != NULL; curr_out = curr_out->next)
         {
         	
		test_output_helper(curr_out);
         	//cout<<"------------- next subAnaIn ioElement --------------- \n";
         }                                                         	                          		
   	 //cout <<"currSubAnaIn is NULL \n";	

      }
   }

   return;	
}

/*****************************************************************************
* This function will be called in pushElement() because
* everytime we want to create new element or update the
* existing element, we overwrite everything that exists
* so we delete all the old output nodes and create new ones
*
* ptr = currDigIn->next_out or
* ptr = currAnaIn->next_out or
* ptr = currSubDigIn->next_out or
* ptr = currSubAnaIn->next_out
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::delete_output(Output_List *ptr)
{
	
	
	Output_List *temp;	// pointer that deletes the node it points to
	
   	if (ptr == NULL)
   	{
   		//cout<<"io_element_control.cpp: There is no output node to delete \n";
   		return 1;
	}
	
	while (ptr->next != NULL)
	{
		//assert(ptr);
		
	 	temp = ptr;
	 	ptr = ptr->next;
	 	delete temp;
	 	//cout<<"io_element_control.cpp: Deleting output node \n";
	
	}
	
	
	//assert(ptr);
	// if the ptr->next == NULL ( there's only one output node)
	delete ptr;
	//cout<<"io_element_control.cpp: Deleting the very last output node \n";
	
	return 1;        	

}


/*****************************************************************************
* Formats the elements and sends the data to the vehicle.
* Adds the Teleos commands to the thruster commands.
* Sends down the arm commands, the auto pilots commands
* Adds the bellypack commands to the thrusters.
* Uses the defined telemetry codes that are in control.h
* These codes must match the vehicle software codes so that each end knows
* what data is being sent back and forth. 
* Initializes the following:
*						1) 
*						2) 
* Returns:
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::send_output_down( int surfVehicle, int digAnalog, int element_num, int digitalVal, float analogVal)
{
	digIterator it;
	
	char command[100];
	char temp[25];
	string cmd;
   	Output_List	*curr_out1;  
   	Output_List	*curr_out2; 


   	if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL ) return -1;

	switch (it->iotype_)
		{
	 	case topDigIn:
	 	    curr_out1 = it->next_out;
			
			// This error checking is needed when the user click
			// something on BPM, we make sure that the digital value
			// sent down is actually 0
			
			if (it->enable_channel_)
				{
			   	it->digital_value_ = digitalVal;	
				// check if the arm enable is On, then send over the command
				// to the sub that will enable the arm (because we should not send
				// over the arm enable command from "switch_arm_enable()")
				// only arm disable will be send from "switch_arm_enable()"
				if (it->element_num_ == 40 )
					{
					char temp[50];
					extern int ack_arm_enable;
					int loop_timeout = 0;
   					ack_arm_enable = 0;
					
					snprintf(temp, 50, "%d|%d\n", SET_ARM_ENABLE, vehicle.arm.arm_enable);
    					tty_send_request(temp);
	    			  	usleep(400000);
	    			  	while(ack_arm_enable == 0)
					   	{
					   	tty_send_request(temp);
					   	usleep(400000);
					   	loop_timeout ++;
					   	if (loop_timeout == 2)
				   			{
					   		alarm_obj.set_other_alarm(30); //generate alarm
					  		ack_arm_enable = 2;
					  		}
						}
	    			  	}
				}
			else
				{
				digitalVal = 0;
			   	it->digital_value_ = 0;
				}
						
		    if (element_num == vehicle.autopilot.autoHead_ch)
		        {
		        extern float dvl_heading;
		        extern float backup_heading;
		        extern int ack_auto_heading;
				int loop_timeout = 0;
				ack_auto_heading = 0;
		        		
		        if(vehicle.autopilot.headingSource == 0) auto_heading_setpoint = vehicle.curr_heading;
	        		if(vehicle.autopilot.headingSource == 1) auto_heading_setpoint = backup_heading;
	        		if(vehicle.autopilot.headingSource == 2) auto_heading_setpoint = dvl_heading;
	        		snprintf(command, 100, "%d|%d\n", AUTO_HEADING_, digitalVal);
				tty_send_request(command);
				usleep(400000);
				while(ack_auto_heading == 0)
					{
				  	tty_send_request(command);
					usleep(400000);
				 	loop_timeout ++;
				  	if (loop_timeout == 2)
				   		{
				   		alarm_obj.set_other_alarm(32); //generate alarm
				   		ack_auto_heading = 2;
				   		}
					}
                                        globalAutoHeadOn = digitalVal;	
					return 1;
				}
			else if (element_num == vehicle.autopilot.autoDepth_ch)
				{
				extern int ack_auto_depth;
				int loop_timeout = 0;
				ack_auto_depth = 0;
					
				auto_depth_setpoint = vehicle.curr_depth;
				snprintf(command, 100, "%d|%d\n", AUTO_DEPTH_, digitalVal);
				tty_send_request(command);
				usleep(400000);
				while(ack_auto_depth == 0)
				   	{
				   	tty_send_request(command);
				   	usleep(400000);
				   	loop_timeout ++;
				   	if (loop_timeout == 2)
				   		{
				   		alarm_obj.set_other_alarm(33); //generate alarm
				   		ack_auto_depth = 2;
				   		}
					}
                        globalAutoDepthOn = digitalVal;
				return 1;
				}
     			else if (element_num == vehicle.autopilot.autoAltitude_ch)
     			 	{
                        // if altimeter i is selected, get value from sub analog 17
                        extern float dvl_altitude;
                        extern int ack_auto_altitude;
				int loop_timeout = 0;
				ack_auto_altitude = 0;
                        		
                        if (vehicle.autopilot.AltitudeSource == 0) auto_depth_setpoint = get_analog_value(0, 17);
				else if (vehicle.autopilot.AltitudeSource == 1)	auto_depth_setpoint = get_analog_value(0, 32);
				else if (vehicle.autopilot.AltitudeSource == 2)
auto_depth_setpoint = vehicle.dvl_altitude;
				snprintf(command, 100,"%d|%d\n", AUTO_ALTITUDE_, digitalVal);
				tty_send_request(command);
				usleep(400000);
				while(ack_auto_altitude == 0)
				   	{
				   	tty_send_request(command);
				   	usleep(400000);
				   	loop_timeout ++;
					if (loop_timeout == 2)
				   		{
				   		alarm_obj.set_other_alarm(42); //generate alarm
				  		ack_auto_altitude = 2;
				   		}
					}
				globalAutoDepthOn = digitalVal;	
				return 1;
				}
			else if (element_num == vehicle.autopilot.autoCruise_ch)
				{
				extern int ack_auto_cruise;
				extern int auto_cruise_use_bottom_lock;
				int loop_timeout = 0;
				ack_auto_cruise = 0;
				if(digitalVal)
					{
					auto_cruise_setpoint = vehicle.curr_vel;
					auto_cruise_lat_setpoint = vehicle.curr_lat_vel;
					}
				else 
					{
					auto_cruise_setpoint = 0;
					auto_cruise_lat_setpoint = 0;
					}
				snprintf(command, 100, "%d|%d|%d\n", AUTO_CRUISE_, auto_cruise_use_bottom_lock, digitalVal);
				tty_send_request(command);
				usleep(400000);
				while(ack_auto_cruise == 0)
				   	{
				   	tty_send_request(command);
				   	usleep(400000);
				   	loop_timeout ++;
				   	if (loop_timeout == 2)
				   		{
				   		alarm_obj.set_other_alarm(34); //generate alarm
				   		ack_auto_cruise = 2;
				   		}
					}
				globalAutoCruiseOn = digitalVal;
				return 1;
				}
				
			// bellypack channel is 1
			else if (element_num == 1)
				{
			    bellypack_value = digitalVal;
				return 1;
				}
			else if (element_num == vehicle.autopilot.depthJogUp_ch) {
				auto_depth_setpoint -= 0.1;		/* it's packaged with the autoheading setpt */	
				return 1;
				}
			else if (element_num == vehicle.autopilot.depthJogDown_ch) {
				auto_depth_setpoint += 0.1;
    /* it's packaged with the autoheading setpt */	
				return 1;
				}
			else 
				{
				while(curr_out1 != NULL)
					{
					//send down the digital as its not a special button
					// IO_ELEM|surveh|board#|elem#|dig_value(intvalue)
					//assert(curr_out1);
	        			snprintf(command, 100, "%d|%d|%d\n",curr_out1->out_board,
						 curr_out1->out_elem_num, digitalVal);

					if (it->element_num_ == 40)
// only do this for channel 40 -> arm enable
				       	{
				       	// if either software or hardware/master switch are off, then
				       	// send down the arm disable cmd to the sub, and also send down
				       	// digital value 0 (even though the actual hardware/master
				       	// switch is still 1 (on) ) for channel 40
						if ( (digitalVal != 1) || (vehicle.arm.arm_enable != 1) )
							{
							char temp[50];
							extern int ack_arm_enable;
							int loop_timeout = 0;
							ack_arm_enable = 0;
							
							snprintf(temp, 50, "%d|%d\n", SET_ARM_ENABLE,0);
    							tty_send_request(temp);
    						    usleep(400000);
							while(ack_arm_enable == 0)
							   	{
							   	tty_send_request(temp);
							   	usleep(400000);
							   	loop_timeout ++;
							   	if (loop_timeout == 2)
							   		{
						   			alarm_obj.set_other_alarm(30); //generate alarm
							   		ack_arm_enable = 2;
							   		}
								}
    							// send down digital value 0 to the sub output channel 8 for arm valve
    							// sending down [board, elem num, digital value \n]
    							char temp_dig[50];
    							snprintf(temp_dig, 50, "%d|%d|%d\n", OUT_GESOUT, 8, 0);
    							tty_send_request(temp_dig);
       						   							    							
    							// break here, so it wont go the the next statement that sends down
    							// digital value read from the surface again
    						        break;
   							}
    			            }
    			        //send the digital after decideing its not a special button auto pilots etc.   
	 	         	tty_send_request(command);  
	 	            curr_out1 = curr_out1->next;
	 	        	}
	 	        break;
	 			}

	 // ------------------------------------ topAnalogIn --------------------------------------			
	        case topAnalogIn:
	
	        	if (it->enable_channel_) it->analog_value_ = analogVal;	
			else
				{
				analogVal = 0.0;
			   	it->analog_value_ = 0.0;
				}
			
                        {
       			it->updateAnalogRaw(analogVal);

			/***************belly pack ************************/
       			if (bellypack_value)
       				{
       				if (element_num == 8 || element_num == 9 || element_num == 10 || element_num == 11)
			    		{
					memset(command, 0, 100);
					if((it = getIOElement(1, 0, 9 , it)) == NULL) return -1;
				
					bellypack_port = it->analog_raw_;
					bellypack_port *= it->analog_gain_;
					bellypack_port += it->analog_offset_;
					
					if((it = getIOElement(1, 0, 8, it)) == NULL) return -1;
						
					bellypack_stbd = it->analog_raw_;
					bellypack_stbd *= it->analog_gain_;
					bellypack_stbd += it->analog_offset_;
										
					analogVal = bellypack_port + bellypack_stbd;
					
					if (analogVal > 5.0) analogVal = 5.0;
					if (analogVal < -5.0)analogVal = -5.0;
											
					memset(temp, 0, 20);
					snprintf(temp, 20, "%d|%4.3f\0", PILOT_SETPT, analogVal);
					strncat(command, temp, 100);
					
					analogVal = bellypack_port - bellypack_stbd;
					
					if (analogVal > 5.0) analogVal = 5.0;
					if (analogVal < -5.0)analogVal = -5.0;
						
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", analogVal);
					strncat(command, temp, 100);
				 	
					// get auto heading
				 	if(auto_heading_setpoint < 0) auto_heading_setpoint = 359;
			
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", auto_heading_setpoint);
					strncat(command, temp, 100);
					
				 	
				 	if((it = getIOElement(1, 0, 10, it)) == NULL) return -1;
					
					analogVal = it->analog_raw_;
					analogVal *= it->analog_gain_;
					analogVal += it->analog_offset_;
			                	
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", analogVal);
					strncat(command, temp, 100);
		
					if((it = getIOElement(1, 0, 11, it)) == NULL) return -1;
					analogVal = it->analog_raw_;
					analogVal *= it->analog_gain_;
					analogVal += it->analog_offset_;
					
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", analogVal);
					strncat(command, temp, 100);
					
					// go grab current autodepth
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", auto_depth_setpoint);
					strncat(command, temp, 100);

					// go grab current autocruise
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\0", auto_cruise_setpoint);
					strncat(command, temp, 100);

					
					// go grab current autocruise lateral
					memset(temp, 0, 20);
					snprintf(temp, 20, "|%4.3f\n", auto_cruise_lat_setpoint);
					strncat(command, temp, 100);
					
					
					tty_send_request(command); //Send PILOT_SETPT
	                    return 1;
					}
				} // end bellypack
       		
		/*************** teleos ************************/
    			else if ((element_num == vehicle.autopilot.foreaft_ch ||
			    element_num == vehicle.autopilot.turns_ch ||
			    element_num == vehicle.autopilot.lateral ||
			    element_num == vehicle.autopilot.vertical) && (teleos_enable)) {
			
				float pilot_db, summed_v, limited_v, max_;
				max_ = 5.00;
				
				//ForeAft Command
       			        memset(command, 0, 100);
				if((it = getIOElement(1, 0,vehicle.autopilot.foreaft_ch, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_foreaft);
				summed_v = summation(pilot_db, telstring.VisionControlStringIn.foreaft_ext_in);		
				limited_v = limiter(summed_v, max_);
				
				teleos_fb_foreaft = limited_v ;
				analogVal = nonlinearMapping(limited_v,max_, vehicle.teleos.st_foreaft,
						vehicle.teleos.curve_mode, vehicle.teleos.kf1_foreaft,
						vehicle.teleos.kf2_foreaft,1);
       			        if(analogVal > 5.00) analogVal = 5.00;
       			        if(analogVal < -5.00) analogVal = -5.00;
				
			
				memset(temp, 0, 20);
				snprintf(temp, 20, "%d|%4.3f\0", PILOT_SETPT, analogVal);
				strncat(command, temp, 100);
				
				//Turns Command
				if((it = getIOElement(1, 0, vehicle.autopilot.turns_ch, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
								
				// set up auto_heading	
				if(analogVal < 1.5) auto_heading_setpoint += 0.025;
				if(analogVal < 2)   auto_heading_setpoint += 0.05;
				if(analogVal < 3)   auto_heading_setpoint += 0.075;
				if(analogVal < 4)   auto_heading_setpoint += 0.125;
		        if(analogVal > -1.5)auto_heading_setpoint -= 0.025;
				if(analogVal > -2)  auto_heading_setpoint -= 0.05;
				if(analogVal > -3)  auto_heading_setpoint -= 0.075;
				if(analogVal > -4)  auto_heading_setpoint -= 0.125;
				if(auto_heading_setpoint >= 360.00) auto_heading_setpoint = 0;
				if(auto_heading_setpoint < 0) auto_heading_setpoint = 359;
				
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_turns);
				summed_v = summation(pilot_db, telstring.VisionControlStringIn.turns_ext_in);	
				limited_v = limiter(summed_v, max_);
				
				teleos_fb_turns = limited_v ;
				analogVal = nonlinearMapping(limited_v, max_, vehicle.teleos.st_turns,
						vehicle.teleos.curve_mode, vehicle.teleos.kf1_turns,
						vehicle.teleos.kf2_turns, 2);
				if(analogVal > 5.00) analogVal = 5.00;
       			        if(analogVal < -5.00) analogVal = -5.00;
				
				vehicle.teleos.stbd_thruster = teleos_fb_foreaft + teleos_fb_turns;
				vehicle.teleos.port_thruster = teleos_fb_foreaft - teleos_fb_turns;
       			
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				//Auto Heading Setpoint 	
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", auto_heading_setpoint);
				strncat(command, temp, 100);
				
				//Lateral Command
				if((it = getIOElement(1, 0, vehicle.autopilot.lateral, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;

				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_lateral);
				summed_v = summation(pilot_db,telstring.VisionControlStringIn.lateral_ext_in);	
				limited_v = limiter(summed_v, max_);
				teleos_fb_lateral = limited_v;
				
				analogVal = nonlinearMapping(limited_v,max_,
						vehicle.teleos.st_lateral, vehicle.teleos.curve_mode,
						vehicle.teleos.kf1_lateral, vehicle.teleos.kf2_lateral, 3);
						
				if(analogVal > 5.00) analogVal = 5.00;
       			        if(analogVal < -5.00) analogVal = -5.00;
			
				vehicle.teleos.lateral_thruster = teleos_fb_lateral;
                        				
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				//Vertical Command
				if((it = getIOElement(1, 0, vehicle.autopilot.vertical, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;

				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_vertical);
				summed_v = summation(pilot_db, telstring.VisionControlStringIn.vertical_ext_in);	
				limited_v = limiter(summed_v, max_);
				teleos_fb_vertical = limited_v;
				
				analogVal = nonlinearMapping(limited_v, max_, vehicle.teleos.st_vertical,
						vehicle.teleos.curve_mode, vehicle.teleos.kf1_vertical,
						vehicle.teleos.kf2_vertical, 4);
				if(analogVal > 5.00) analogVal = 5.00;
       			        if(analogVal < -5.00) analogVal = -5.00;

				vehicle.teleos.vertical_thruster = teleos_fb_vertical;
				
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				// autodepth
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", auto_depth_setpoint);
				strncat(command, temp, 100);
				
                                // autocruise
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", auto_cruise_setpoint);
				strncat(command, temp, 100);
							
				        // autocruise lateral 
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\n", auto_cruise_lat_setpoint);
				strncat(command, temp, 100);
									
				tty_send_request(command); //Send PILOT_SETPT
	                        return 1;
			
			} 	//end if teleos enable
       			   	

			/*************** pilot control ****************************/
			else if (element_num == vehicle.autopilot.foreaft_ch ||
			    element_num == vehicle.autopilot.turns_ch ||
			    element_num == vehicle.autopilot.lateral ||
			    element_num == vehicle.autopilot.vertical)
			    	{
			    	float pilot_db, summed_v, limited_v, max_;
				max_ = 5.00;
				
				memset(command, 0, 100);
				// go get foreaft_ch
				if((it = getIOElement(1, 0, vehicle.autopilot.foreaft_ch, it)) == NULL)	return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				
				memset(temp, 0, 20);
				snprintf(temp, 20, "%d|%4.3f\0", PILOT_SETPT, analogVal);
				strncat(command, temp, 100);
				float joystick_foreaft = analogVal;
			
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_foreaft);
				summed_v = summation(pilot_db,telstring.VisionControlStringIn.foreaft_ext_in);		
				limited_v = limiter(summed_v, max_);
				teleos_fb_foreaft = limited_v ;
		
				// go get turns
				if((it = getIOElement(1, 0, vehicle.autopilot.turns_ch, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				// set up auto_heading	
				if(analogVal < 1.5) auto_heading_setpoint += 0.025;
				if(analogVal < 2)   auto_heading_setpoint += 0.050;
				if(analogVal < 3)   auto_heading_setpoint += 0.075;
				if(analogVal < 4)   auto_heading_setpoint += 0.125;
		                if(analogVal > -1.5)auto_heading_setpoint -= 0.025;
				if(analogVal > -2)  auto_heading_setpoint -= 0.05;
				if(analogVal > -3)  auto_heading_setpoint -= 0.075;
				if(analogVal > -4)  auto_heading_setpoint -= 0.125;
				if(auto_heading_setpoint >= 360.00) auto_heading_setpoint = 0;
				if(auto_heading_setpoint < 0) auto_heading_setpoint = 359;
				
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
								
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_turns);
				summed_v = summation(pilot_db,telstring.VisionControlStringIn.turns_ext_in);	
				limited_v = limiter(summed_v, max_);
				teleos_fb_turns = limited_v ;

                                vehicle.teleos.stbd_thruster = teleos_fb_foreaft + teleos_fb_turns;
				vehicle.teleos.port_thruster = teleos_fb_foreaft - teleos_fb_turns;
       			
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0",auto_heading_setpoint);
				strncat(command, temp, 100);
			
				// go get lateral
				if((it = getIOElement(1, 0, vehicle.autopilot.lateral, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_lateral);
				summed_v = summation(pilot_db,telstring.VisionControlStringIn.lateral_ext_in);	
				limited_v = limiter(summed_v, max_);
				teleos_fb_lateral = limited_v;

				
				// go get vertical
				if((it = getIOElement(1, 0, vehicle.autopilot.vertical, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				pilot_db = pilotDeadBand(analogVal, max_, vehicle.teleos.db_vertical);
				summed_v = summation(pilot_db, telstring.VisionControlStringIn.vertical_ext_in);	
				limited_v = limiter(summed_v, max_);
				teleos_fb_vertical = limited_v;

				// go grab current autodepth
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", auto_depth_setpoint);
				strncat(command, temp, 100);

				// go grab current autocruise
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", auto_cruise_setpoint);
				strncat(command, temp, 100);
				
				// go grab current autocruise lateral
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\n", auto_cruise_lat_setpoint);
				strncat(command, temp, 100);
				
				tty_send_request(command); //Send PILOT_SETPT
	                return 1;	
				}
					
			/* analogs for the cam control */
			if (element_num == vehicle.camera.command_shoulder_channel_top ||
	    		    element_num == vehicle.camera.command_pan_channel_top ||
			    element_num == vehicle.camera.command_tilt_channel_top)
			    	{
				memset(command, 0, 100);
				
				// go get shoulder
				if((it = getIOElement(1, 0, vehicle.camera.command_shoulder_channel_top, it)) == NULL) return -1;

				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "%d|%4.3f\0", CAM_SETPT, analogVal);
				strncat(command, temp, 100);
				// go get pan
				if((it = getIOElement(1, 0, vehicle.camera.command_pan_channel_top, it)) == NULL) return -1;
	
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				// go get tilt
				if((it = getIOElement(1, 0, vehicle.camera.command_tilt_channel_top, it)) == NULL) return -1;
	
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\n", analogVal);
				strncat(command, temp, 100);
				
				tty_send_request(command); //Send CAM_SETPT
	                        return 1;
				}
			
			/* analogs for the arm control */
			if (element_num == vehicle.arm.command_shoulder_channel_top ||
			    element_num == vehicle.arm.command_swing_channel_top ||
			    element_num == vehicle.arm.command_elbow_channel_top ||
			    element_num == vehicle.arm.command_pitch_channel_top ||
			    element_num == vehicle.arm.command_yaw_channel_top)
			    	{
				memset(command, 0, 100);
				
				// go get shoulder
				if((it = getIOElement(1, 0, vehicle.arm.command_shoulder_channel_top, it)) == NULL) return -1;
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "%d|%4.3f\0", ARM_SETPT, analogVal);
				strncat(command, temp, 100);
				
				// go get swing
				if((it = getIOElement(1, 0, vehicle.arm.command_swing_channel_top, it)) == NULL) return -1;
				
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				// go get elbow
				if((it = getIOElement(1, 0, vehicle.arm.command_elbow_channel_top, it)) == NULL) return -1;
				
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);

                                // go get pitch
				if((it = getIOElement(1, 0, vehicle.arm.command_pitch_channel_top, it)) == NULL) return -1;
				
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\0", analogVal);
				strncat(command, temp, 100);
				
				
				// go get yaw
				if((it = getIOElement(1, 0, vehicle.arm.command_yaw_channel_top, it)) == NULL) return -1;
				
				analogVal = it->analog_raw_;
				analogVal *= it->analog_gain_;
				analogVal += it->analog_offset_;
				memset(temp, 0, 20);
				snprintf(temp, 20, "|%4.3f\n", analogVal);
				strncat(command, temp, 100);
				
				tty_send_request(command); //Send ARM_SETPT
	                        return 1;	
				}
			else //the analog chanel is not for thrusters or the arm or the camera
				{
				curr_out2 = it->next_out;
				float gain = it->analog_gain_;
				float offset = it->analog_offset_;
	       			it->updateAnalogRaw(analogVal);
				analogVal *= gain;
				analogVal += offset;
       				it->updateAnalogValue(analogVal);
 
		        	while(curr_out2 != NULL)
					{
					// IO_ELEM|surveh|board#|elem#|ana_value(float value)
					snprintf(command, 100, "%d|%d|%4.2f\n",curr_out2->out_board,
					curr_out2->out_elem_num, analogVal);
	 		                tty_send_request(command);
					curr_out2 = curr_out2->next;
	 	        		}	
                                }		// end else
	   		break;
	   		}
	}
	
	return 1;

}



/*****************************************************************************
* This function is called by telemetry.cpp to send A DIGITAL
* element default down to the sub
* We call this when we want to send down new default from a
* selected digital element that we usually open from the
* element properties window
*
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/


int
IOElementControl::send_default_down(int surfVehicle, int digAnalog, int element_num)
{
	digIterator 	it;
   	Output_List	*curr_out1;  
	char		command[100];
	char*		defaultPtr;

   	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL ) {
   		return -1;
   	}
  
	curr_out1 = it->next_out;
	while(curr_out1 != NULL) {
	        int n;
		char defaultString[32];
		memset(defaultString, 0, 32);
		
		strncpy(defaultString, it->defaults_.c_str(), 32);
		
		for (defaultPtr = defaultString; *defaultPtr != '\0';
		     defaultPtr++) {
			
		     assert(defaultPtr);
			if (*defaultPtr == ':')
				*defaultPtr = '|';
						
		}
	       	snprintf(command, 100, "%d|%d|%d|%s\n", DIG_DEFAULTS, curr_out1->out_board,
			 curr_out1->out_elem_num, defaultString);
	       	
	       	//cout <<"io_element_control.cpp : send down : "<<command<<endl;
	       	tty_send_request(command);
	 	curr_out1 = curr_out1->next;
	}
	return 1;
}

/*****************************************************************************
* This function is called by telemetry.cpp to send ALL DIGITAL
* elements defaults down to the sub
* We call this when we start establish a telemetry so that the
* sub know what the default status for ALL the digital elements
*
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int IOElementControl::send_defaults_down()
{
	digIterator 	it;
   	Output_List	*curr_out1;  
	char		command[100];
	char*		defaultPtr;
	
	for (int i = 0; i < topdigitalInList.size(); i++) {
		it = &topdigitalInList[i];
		
		curr_out1 = it->next_out;
		while(curr_out1 != NULL) {
		        int n;
			char defaultString[32];
			
			memset(defaultString, 0, 32);
			strncpy(defaultString, it->defaults_.c_str(), 32);
			
			for (defaultPtr = defaultString; *defaultPtr != '\0'; defaultPtr++) {
			     assert(defaultPtr);
				if (*defaultPtr == ':')
					*defaultPtr = '|';
			}
	        	snprintf(command, 100, "%d|%d|%d|%s\n", DIG_DEFAULTS, curr_out1->out_board,
	        		curr_out1->out_elem_num, defaultString);
	 	      	tty_send_request(command);
	 		curr_out1 = curr_out1->next;
		}
	}
	return 1;
}

/*****************************************************************************
* Returns the output string for an element.  ie : MPL4205 channel 5 
* Initializes the following:
*						1) 
*						2) 
* Returns: -1 if no element and the string if an element
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

string
IOElementControl::display_output(int surfVehicle, int digAnalog, int element_num)
{
	anaIterator it;
	
	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL )
  	{
   		//cout <<"io_element_control.cpp : Can not find the element : "
 		//	<< surfVehicle<<" "<<digAnalog<<" "<<element_num<<endl;
   			
 		return "-1";
 	}
  	   	
  	return it->out_string;
  		

}





/*****************************************************************************
* traverse everything to see if the button connection already exists in the
* io element output data base
* it returns the "type"  when it finds it
*
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::check_io_output_db  (int out_board, int out_elem_num )
{
	//int size = topdigitalInList.size();
	//cout <<"io_element_control.cpp: board and elem num " <<out_board <<", "<<out_elem_num<<endl;
	
	// top digital in
   	for(int i = 0; i < topdigitalInList.size(); i++)
   	{
		assert(currDigIn);
		currDigIn = &topdigitalInList[i];
		
		if (currDigIn == NULL)
			break;
		
		if(currDigIn->next_out == NULL)
			break;
			
		curr_out = currDigIn->next_out;
		
	 	for (curr_out ; curr_out != NULL; curr_out = curr_out->next)
		{
			
			if ((curr_out->out_board == out_board) && (curr_out->out_elem_num == out_elem_num))
			{
				//cout<<"curr_out->out_board = "<< curr_out->out_board<<" \n" ;
				//cout<<"curr_out->out_elem_num = "<< curr_out->out_elem_num<<" \n" ;
				return topDigIn;
		  	}
						
		}	// end while	  	
	   }	// end for
	
	  // sub digital in
	  for(int i = 0; i < subdigitalInList.size(); i++)
   	  {
		assert(currSubDigIn);
		currSubDigIn = &subdigitalInList[i];
		
		if (currSubDigIn == NULL)
			break;
		
		if(currSubDigIn->next_out == NULL)
			break;
			
		curr_out = currSubDigIn->next_out;
		
	 	for (curr_out ; curr_out != NULL; curr_out = curr_out->next)
		{
			
			if ((curr_out->out_board == out_board) && (curr_out->out_elem_num == out_elem_num))
			{			
				return subDigIn;
		  	}
						
		}	// end while	  	
	  }	// end for
	
	// top analog in
	for(int i = 0; i < topanalogInList.size(); i++)
   	{
		assert(currAnaIn);
		currAnaIn = &topanalogInList[i];
		
		if (currAnaIn == NULL)
			break;
		
		if(currAnaIn->next_out == NULL)
			break;
			
		curr_out = currAnaIn->next_out;
		
	 	for (curr_out ; curr_out != NULL; curr_out = curr_out->next)
		{
			
			if ((curr_out->out_board == out_board) && (curr_out->out_elem_num == out_elem_num))
			{			
				return topAnalogIn;
		  	}
						
		}	// end while	  	
	   }	// end for
	
	
	  // sub analog in
	for(int i = 0; i < subanalogInList.size(); i++)
   	{
		assert(currSubAnaIn);
		currSubAnaIn = &subanalogInList[i];
		
		if (currSubAnaIn == NULL)
			break;
		
		if(currSubAnaIn->next_out == NULL)
			break;
			
		curr_out = currSubAnaIn->next_out;
		
	 	for (curr_out ; curr_out != NULL; curr_out = curr_out->next)
		{			
			
			if ((curr_out->out_board == out_board) && (curr_out->out_elem_num == out_elem_num))
			{				
				return subAnalogIn;
		  	}
						
		}	// end while	  	
	   }	// end for
	
	
	   //cout <<"io_element_control.cpp: There is no such output connection in IO output database \n";
	
	
		// top analog out
	for(int i = 0; i < topanalogOutList.size(); i++)
   	{
		assert(currAnaOut);
		currAnaOut = &topanalogOutList[i];
		
		if (currAnaOut == NULL)
			break;
		
		if(currAnaOut->next_out == NULL)
			break;
			
		curr_out = currAnaOut->next_out;
		
	 	for (curr_out ; curr_out != NULL; curr_out = curr_out->next)
		{
				
			if ((curr_out->out_board == out_board) && (curr_out->out_elem_num == out_elem_num))
			{			
				return topAnalogOut;
		  	}
						
		}	// end while	  	
	   }	// end for
	
	
	   //cout <<"io_element_control.cpp: There is no such output connection in IO output database \n";
	
	
	          	        	
	return 0;
}


/*****************************************************************************
* Check button database for the same name of connection...
* button can NOT have the SAME name and connection (board# and elem#)
* Initializes the following:
*						1) 
*						2) 
* Returns: the size of the data base
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::check_button_db (string name, int board, int elem_num)
{
	if (first_but == NULL)
		return 0;
		
	but_ptr = first_but;
	assert (but_ptr);
	
               while ( but_ptr != NULL )
               {                         	
               	// if both the name and connection are the same
               	if ( but_ptr->name == name && ( (but_ptr->board == board) && (but_ptr->elem_num == elem_num) ) )
                            	return 90;              	
                	//  if the name exists, but different connection  -> error
               	if ( but_ptr->name == name  )
                            	return 91;
                           // if the connection exists but different name
                           if ( (but_ptr->board == board) && (but_ptr->elem_num == elem_num)  )
                            	return 92;

                	//if ( but_ptr->name == name || ( (but_ptr->board == board) && (but_ptr->elem_num == elem_num) ) )
                           // 	return button_exist;
                            	
                 	but_ptr = but_ptr->next;

               }

               return 0;

}

/*****************************************************************************
* Used by detritus and tools as a helper function.
* Converts the output nodes for the passed element into a string for Tcl to access.  
* Initializes the following:
*						1) out_string
*						2) 
* Returns: False if element does not exist. True if successfull
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::set_out_string(IOElement *io_element_ptr, Output_List *ptr)
{
	char out_str[512];
	char temp_out[50];
	Output_List *temp;
	memset (out_str, 0, 512);
	
	if (io_element_ptr == NULL )
	{
	 	//cout<<"io_element_control.cpp: no element found\n";
	 	return 0;
	}
	
	for (temp = io_element_ptr->next_out; temp != NULL; temp = temp->next)
	{
		memset(temp_out, 0, 50);
		snprintf (temp_out, 50, "%d|%d|", temp->out_board, temp->out_elem_num);
		strcat(out_str, temp_out);
	}	
		
	string str(out_str);
	//cout<<"THE FINAL STRING : "<<str<<endl;
	io_element_ptr->out_string = str;
	
        return 1;
}

/******************************************************************************
* Used by detritus and tools as a helper function.
* Deletes the current output so that a new one can be added.
* Initializes the following:
*						1) 
*						2) 
* Returns: False if output does not exist. True if successfull
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::delete_single_output (int elem_num, Output_List *ptr)
{
	Output_List *temp;
	Output_List *prev_ptr;
	digIterator it;
	
	if (ptr == NULL)
		return 0;
		
	if ((it = getIOElement(1, 1, elem_num, it)) == NULL )
		return 0;
	
	 // if removing the first node
	if (ptr == it->next_out)
	{
	
	
		it->next_out = ptr->next;
	 	
	 	if (ptr != NULL)
	 	{

		 	delete ptr;
		 	return 0;
		}
		
	
	 	return 1;
	}
	
	
     	// if it is in the middle
     	for (prev_ptr = it->next_out; prev_ptr->next != ptr; prev_ptr = prev_ptr->next)
     	{
     	 	// do nothing
     	}
     	
     	
     	assert(ptr);
     	temp = ptr->next;
     	prev_ptr->next =  temp;
       	delete ptr;
     	
  	return 1;
}


/***************************************************************************
* For analog output on the surface.
* This function is called in commands.c
* Deletes the input connection for an Analog Out element.
* Initializes the following:
*						1) 
*						2) 
* Returns: False if element does not exist. True if successfull
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::delete_single_input (int elem_num)
{
        ana_out_iterator it;
        // This is to update the IOElement pointer so that it points to the
	// correct Analog Out channel
	if ( (it = ioElementControl.getIOElement(1, 3, elem_num, it) ) == NULL)	return 0;	
	if (it->next_out != NULL)
		{
		//cout <<"io_element_control.cpp: deleting single input : " << it->next_out->out_board << " " << it->next_out->out_elem_num<<endl;
		delete it->next_out;
		it->next_out = NULL;
		it->out_string = "";
		}
  	return 1;
}



/***************************************************************************
* Checks to make sure that the output is not already used. ie the button is
* present on the screen already  If it is then the function 
* overwrites the old button with the new parameters.
* Return 1 on success and 0 otherwise
* Initializes the following:
*						1) Creates a new button
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::add_to_button_db ( string name, string type, int out_board, int out_elem_num, int x, int y, string color, int state, int screen )
{
	// Create a node that contains button output info
	
	//cout<<" Screen is : " <<screen<<endl;
	 	// if it has already exists in button database, then just OVERWRITE the old one and return 1 as success
     	// Note : check_button_db will return a proper pointer "but_ptr" that needs to be replaced
     	if (check_button_db (name, out_board, out_elem_num) > 0)
     	{                 		
     	
     		
     		//cout<<"io_element_control.cpp: Button exists in its database already \n" ;
     		//temp_but = but_ptr->next;
     		if (screen == 1)
     		{     	
     			but_ptr->name = name;
		     	but_ptr->type = type;
     			but_ptr->color = color;
     			but_ptr->state = state;	
     			but_ptr->x = x;
     			but_ptr->y = y;                   		 	     	      	     		
     		}
     		else
     		{
     			but_ptr->name = name;
		     	but_ptr->type = type;
     			but_ptr->color = color;
     			but_ptr->state = state;	                                      			
     			but_ptr->x2 = x;
     			but_ptr->y2 = y;     	     		     	
     		}
     		
     		but_ptr->color = color;
     		     	                 		
     		
     		assert(but_ptr);
     		//display_button_db();
     		return 1;                                	
     	}

     	
	
	
	Button *new_but_node;
 	new_but_node = new Button;
     	new_but_node->board = out_board;
     	new_but_node->elem_num = out_elem_num;
     	new_but_node->name = name;
     	new_but_node->type = type;
     	
     	new_but_node->color = color;
     	new_but_node->state = state;
     	new_but_node->width = strlen(name.c_str()) * 10;
     	
     	if (screen == 1)
     	{
     		new_but_node->x = x;
     		new_but_node->y = y;
     		new_but_node->x2 = -1;
     	 	new_but_node->y2 = -1;     	
     	}
     	else
     	{
     	      	new_but_node->x = -1;
     	 	new_but_node->y = -1;      	
     	      	new_but_node->x2 = x;
     		new_but_node->y2 = y;
     		
     	}
     	
     	// Create a temporary pointer
     	Button *temp_but;
     	
     	
     	
                  	   	
     	
     	// it doesn exist in Button database yet, then add it to the end of button database     		                                                                                                           		
     	new_but_node->next = NULL;			// we have this coz we're going to insert it at the end
     	
     	
     		
     	temp_but = first_but;
     	
     	
     	// first node
     	if (temp_but == NULL)
     		first_but = new_but_node;
     		
     	else
     	{
     		for (but_ptr = first_but; but_ptr != NULL; but_ptr = but_ptr->next)
     		{
     			temp_but = but_ptr;     		                                              	
     		}
  		
     		// insert new node at the end
     		assert(temp_but);
     		temp_but->next = new_but_node;
  	}
     	  	
  	bcount++;
  	
   	//display_button_db();	
     	return 1;     	
     	 	
     	

}
/***************************************************************************
* Removes a button from the data base.
* Initializes the following:
*						1) 
*						2) 
* Returns: False if button does not exist. True if successfull
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::remove_button_from_db (int board, int elem_num, int screen)
{
	Button *temp;
	Button *prev_but;
	
	//cout <<"What's the name "<<name<<"\n";      	 		
     	
	//assert (first_but);
	
	if (first_but == NULL)
		return -1;
	
	but_ptr = first_but;
	
	
	// Traverse the button database to find the node we want to delete	 		
 	for (but_ptr; but_ptr != NULL; but_ptr = but_ptr->next)
    	{
     		assert (but_ptr);
     	 	if (but_ptr->board == board && but_ptr->elem_num == elem_num)
     	 	{
  			// found it 	 		
     	 		break;
     		}
     		
     		    		   		     	 		                 	 	                               	 		 	    	 	
     	 }
     	
     	
     	 // NOW START REMOVING
     	 if (screen == 1)
     	 {
     	 	// if the button still exist  on the other screen     	 	
     	  	if (but_ptr->x2 != -1 && but_ptr->y2 != -1)
     	  	{
     	  	 	but_ptr->x = -1;
     	  	 	but_ptr->y = -1;
     	  	             return 1;     	  	 	
     	  	}                              	
     	 }
     	
     	
     	 if (screen == 2)
     	 {
     	 	// if the button still exist  on the other screen     	 	
     	  	if (but_ptr->x != -1 && but_ptr->y != -1)
     	  	{
     	  	 	but_ptr->x2 = -1;
     	  	 	but_ptr->y2 = -1;
     	  	 	return 1;        	  	
     	  	}                                             	
     	 }
     	
     	
     	
     	 // if removing the first node
	if (but_ptr == first_but)
	{
	             first_but = but_ptr->next;
	             delete but_ptr;
		//cout<<"io_element_control.cpp: Deleting the first Button node \n";
	 	
		bcount--;
	 	//display_button_db();
	 	
	 	return 1;
	}
	
     	 // nothing to be removed
     	 if (but_ptr == NULL || first_but == NULL)
     	 	return 0;
     	
     	 // if it is in the middle
     	 for (prev_but = first_but; prev_but->next != but_ptr; prev_but = prev_but->next)
     	 {
     	 	// do nothing
     	 }
     	
     	
     	 assert(but_ptr);
     	 temp = but_ptr->next;
     	
     	
     	 prev_but->next =  temp;
     	 delete but_ptr;
     	 bcount--;
     	 if (bcount == 0)
	{
		first_but = NULL;
		but_ptr = NULL;
	}
	
	//cout <<"io_element_control : button count : "<<bcount<<endl;
     	 //display_button_db();                         	
     	 return 1;
}


/***************************************************************************
* For developement for checking the database for the buttons
* Deletes the input connection for an Analog Out element.
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
void
IOElementControl::display_button_db ()
{
	if (first_but == NULL)
	{
		//cout<<"io_element_control.cpp: No button left \n";
		return;
	}
	Button *ptr;
	ptr = first_but;
	
	assert (ptr);
	int count = 0;
	
               while ( ptr != NULL )
               {
               		cout<<"\n---------------BUTTON DATABASE--------------"<<endl;               	
                	cout<<"io_element_control.cpp: ptr->name "<<ptr->name<<endl;
                	cout<<"io_element_control.cpp: ptr->board "<<ptr->board<<endl;
                	cout<<"io_element_control.cpp: ptr->elem_num "<<ptr->elem_num<<endl;
                	cout<<"io_element_control.cpp: ptr->x "<<ptr->x <<endl;
                	cout<<"io_element_control.cpp: ptr->y "<<ptr->y <<endl;
                	cout<<"io_element_control.cpp: ptr->x2 "<<ptr->x2 <<endl;
                	cout<<"io_element_control.cpp: ptr->y2 "<<ptr->y2 <<endl;
                	
                	cout<<"----------------------------------------------\n";
                	    	
                	count++;
                 	ptr = ptr->next;

               }

               cout<<"\n---------Button Database Size : "<<count<<endl;
               return;

}






/***************************************************************************
* Check slidebar database for the same name of connection...
* slidebar can NOT have the SAME name and connection (board# and elem#)
*
* Initializes the following:
*						1) 
*						2) 
* Returns: False if Slider does not exist. 
*		10 Both name and connection are the same
*		11 Name same, connection different
*		12 Connection same, allow user to give new name for it.
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/int
IOElementControl::check_slidebar_db (string name, int board, int elem_num)
{
	if (first_slide == NULL)
		return 0;
		
	slide_ptr = first_slide;
	assert (slide_ptr);
	
               while ( slide_ptr != NULL )
               {
               	// Both name and connection are the same, user just want to reposition slidebar             	
               	if ( slide_ptr->name == name && ( (slide_ptr->board == board) && (slide_ptr->elem_num == elem_num) ) )
                            	return slidebar_exist;     // return 10

                	// The name is the same, but different connection -> display error message	
                	if ( slide_ptr->name == name  )
                            	return 11;                                                                  	
                            	
                 	// The connection exist, want to rename it.
                	if ( (slide_ptr->board == board) && (slide_ptr->elem_num == elem_num) )
                            	return 12;
                            	
                 	slide_ptr = slide_ptr->next;

               }

               return 0;

}




/***************************************************************************
* This will check if the io elem output has the same output, then it will delete it first and then add it to
* the slidebar output database, if the output slidebar db already has one, then replace / overwrite it
* Return 1 on success and 0 otherwise
* Initializes the following:
*						1) 
*						2) 
* Returns: False if element does not exist. True if successfull
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::add_to_slidebar_db ( string name, int out_board, int out_elem_num, float value, int x, int y, string color,  int screen )
{
	
	// if it has already exists in slidebar database, then just overwrite the old one and return 1 as success
     	// Note : check_slidebar_db will return a proper pointer "slide_ptr" that needs to be replaced
     	if (check_slidebar_db (name, out_board, out_elem_num) > 0 )
     	{                 		
     	
     		//cout<<"io_element_control.cpp: slidebar exists in its database already \n" ;
     		
     		if (screen == 1)
     		{     		
     			slide_ptr->x = x;
     			slide_ptr->y = y;                   		 	     	      	     		
     		}
     		else
     		{			                                        			
     			slide_ptr->x2 = x;
     			slide_ptr->y2 = y;     	     		     	
     		}
     		
     		slide_ptr->name = name;
     		slide_ptr->color = color;
     		
     		assert(slide_ptr);
     		//display_slidebar_db();
     		return 1;                                	
     	}
     		
     	

	
	// Create a node that contains slidebar output info
	Slidebar *new_slide_node;
 	new_slide_node = new Slidebar;
     	new_slide_node->board = out_board;
     	new_slide_node->elem_num = out_elem_num;
     	new_slide_node->name = name;
     	new_slide_node->color = color;
     	new_slide_node->value = value;
     	
     	
     	if (screen == 1)
     	{
     		new_slide_node->x = x;
     		new_slide_node->y = y;
     		new_slide_node->x2 = -1;
     	 	new_slide_node->y2 = -1;     	
     	}
     	else
     	{
     	      	new_slide_node->x = -1;
     	 	new_slide_node->y = -1;      	
     	      	new_slide_node->x2 = x;
     		new_slide_node->y2 = y;
     		
     	}
     	
     	
     	// Create a temporary pointer
     	Slidebar *temp_slide;
     	
     	
     	/**************************************************************************************************/
     	
                  	   	
     	
     	// it doesn exist in slidebar database yet, then add it to the end of slidebar database     		                                                                                                           		
     	new_slide_node->next = NULL;			// we have this coz we're going to insert it at the end
     	
     	temp_slide = first_slide;
     	
     	
     	// first node
     	if (temp_slide == NULL)
     		first_slide = new_slide_node;
     		
     	else
     	{
     		for (slide_ptr = first_slide; slide_ptr != NULL; slide_ptr = slide_ptr->next)
     		{
     			temp_slide = slide_ptr;     		                                              	
     		}
  		
     		// insert new node at the end
     		assert(temp_slide);
     		temp_slide->next = new_slide_node;
  	}
     	
  	scount++;
  	//display_slidebar_db();	
     	return 1;          	 	        	

}
     	
//????????????????????????????????????????????
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::remove_slidebar_from_db (int board, int elem_num, int screen)
{
	int found = -1;
	Slidebar *temp = NULL;
	Slidebar *prev_slide = NULL;
	
	
     	
     	assert (first_slide);
     	assert(slide_ptr);
	slide_ptr = first_slide;
	
	
	// Traverse the slidebar database to find the node we want to delete	 		
 	for (slide_ptr; slide_ptr != NULL; slide_ptr = slide_ptr->next)
    	{
     		assert (slide_ptr);
     		//cout <<"slide_ptr->board is " << slide_ptr->board<<endl;
     	 	//cout <<"slide_ptr->board is " << slide_ptr->board<<endl;
     	 		
     	 	if (slide_ptr->board == board && slide_ptr->elem_num == elem_num)
     	 	{
     	 		found = 1;	 		
     	 		break;
     		}                                                              		    		   		      		                 	 	                               	 		 	    	 	
     	 }                                                                            	
     	
     	
	 printf("---------------- Testing here--------------- \n" );		
     	
     	
              if (found == -1)
     	 	return -1;
     	
     	  // NOW START REMOVING
     	 if (screen == 1)
     	 {
     	 	// if the button still exist  on the other screen     	 	
     	  	if (slide_ptr->x2 != -1 && slide_ptr->y2 != -1)
     	  	{
     	  	 	slide_ptr->x = -1;
     	  	 	slide_ptr->y = -1;
     	  	             return 1;     	  	 	
     	  	}                              	
     	 }
     	
     	
     	 if (screen == 2)
     	 {
     	 	// if the button still exist  on the other screen     	 	
     	  	if (slide_ptr->x != -1 && slide_ptr->y != -1)
     	  	{
     	  	 	slide_ptr->x2 = -1;
     	  	 	slide_ptr->y2 = -1;
     	  	 	return 1;        	  	
     	  	}                                             	
     	 }

     	 // if removing the first node
	if (slide_ptr == first_slide)
	{
	             first_slide = slide_ptr->next;
	
	             delete slide_ptr;
		//cout<<"io_element_control.cpp: Deleting the first Slidebar node \n";
	 	
		scount--;
	 	//display_slidebar_db();
	 	return 1;
	}
	
     	 // nothing to be removed
     	 if (slide_ptr == NULL || first_slide == NULL)
     	 	return 0;
     	
     	 for (prev_slide = first_slide; prev_slide->next != slide_ptr; prev_slide = prev_slide->next)
     	 {
     	 	// do nothing
     	 }
     	
     	 //cout<<"GET HERE THA \n";
     	 assert(slide_ptr);
     	 temp = slide_ptr->next;
     	 //assert(temp);
     	

     	 prev_slide->next =  temp;
     	 delete slide_ptr;
     	 scount--;
     	
     	 if (scount == 0)
     	 {
     	  	first_slide = NULL;
     	  	slide_ptr = NULL;
     	 }
     	
     	 //display_slidebar_db();                         	
     	
     	
     	
     	 return 1;
     	
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
void
IOElementControl::display_slidebar_db ()
{
	if (first_slide == NULL)
	{
		//cout<<"io_element_control.cpp: There's no more slidebar left \n";
	        return;
	}
	
	slide_ptr = first_slide;
	assert (slide_ptr);
	
	int count = 0;
	
               while ( slide_ptr != NULL )
               {
               		
               		cout<<"\n---------------SLIDEBAR DATABASE--------------"<<endl;               	
                	cout<<"io_element_control.cpp: slide_ptr->name "<<slide_ptr->name<<endl;
                	cout<<"io_element_control.cpp: slide_ptr->board "<<slide_ptr->board<<endl;
                	cout<<"io_element_control.cpp: slide_ptr->elem_num "<<slide_ptr->elem_num<<endl;
                	cout<<"io_element_control.cpp: slide_ptr->x "<<slide_ptr->x <<endl;
                	cout<<"io_element_control.cpp: slide_ptr->y "<<slide_ptr->y <<endl;
                	cout<<"io_element_control.cpp: slide_ptr->x2 "<<slide_ptr->x2 <<endl;
                	cout<<"io_element_control.cpp: slide_ptr->y2 "<<slide_ptr->y2 <<endl;
                	
                	cout<<"----------------------------------------------\n";
                	  	
                	count++;
                 	slide_ptr = slide_ptr->next;

               }

               cout<<"\n---------Slidebar Database Size : "<<count<<endl;
               return;

}



/***************************************************************************
* This will return a string that contains information of which database the output
* has already defined before
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::show_connection_existence( int type )
{
	
  	switch (type)
  	{	
  		case topDigIn:
  			strcpy( result_string, "Surface Digital Input" );
  			break;
  		
  		case subDigIn:
  		             strcpy( result_string, "Vehicle Digital Input" );
  			break;
  			
  		case topAnalogIn:
  			strcpy( result_string, "Surface Analog Input" );
  			break;
  			
  		case subAnalogIn:
  			strcpy( result_string, "Vehicle Analog Input" );
  			break;
  			
  	  	case button_exist:
  	  	         	strcpy( result_string, "Button Database" );
  			break;
  	  		
  	  	case slidebar_exist:
  	  		strcpy( result_string, "Slidebar Database" );  			
  	  		break;
  	  		
  	    	default:
  	    		break;  	
  	
  	}


   	return result_string;
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/    	
int
IOElementControl::get_but_state(int board, int elem_num)
{

		if (first_but == NULL)
			return -1;
		
		but_ptr = first_but;
		assert (but_ptr);
	
             	while ( but_ptr != NULL )
               	{                         	
                		if ( but_ptr->board == board && but_ptr->elem_num == elem_num)
                		{
                			/*
                		   	cout<<"io_element_control.cpp: but_ptr->board is "<<but_ptr->board<<endl;
                            	 	cout<<"io_element_control.cpp: but_ptr->elem_num is "<<but_ptr->elem_num<<endl;
                            	 	cout<<"io_element_control.cpp: but_ptr->state is "<<but_ptr->state<<endl;
                            	 	*/
                            	 	
                            		return but_ptr->state;
                            	}
                 	but_ptr = but_ptr->next;

  		}
  	
  	return -1;

}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
int
IOElementControl::set_but_state(int board, int elem_num, int state)
{

		if (first_but == NULL)
			return -1;
		
		but_ptr = first_but;
		assert (but_ptr);
	
             	while ( but_ptr != NULL )
               	{                         	
                		if ( but_ptr->board == board && but_ptr->elem_num == elem_num)
                            	{	
                            		// set the new state
                            		 but_ptr->state = state;
                            		
                            		 /*
                            		 cout<<"io_element_control.cpp: but_ptr->board is "<<but_ptr->board<<endl;
                            	 	 cout<<"io_element_control.cpp: but_ptr->elem_num is "<<but_ptr->elem_num<<endl;                            	 	
                            	 	 cout<<"io_element_control.cpp: but_ptr->state is "<<but_ptr->state<<endl;
                            	 	 */
                            	 	
                            	 	 return state;                                                 		
                            	}
                            	
                 	but_ptr = but_ptr->next;

  	}
  	
  	return -1;

}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
float
IOElementControl::get_slide_value(int board, int elem_num)
{

	if (first_slide == NULL)
			return 0;
		
		slide_ptr = first_slide;
		assert (slide_ptr);
	
              	while ( slide_ptr != NULL )
               	{                         	
                		if ( slide_ptr->board == board && slide_ptr->elem_num == elem_num)
                            		return slide_ptr->value;
                            	
                 		slide_ptr = slide_ptr->next;

               	}

                 return -1;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::set_slide_value(int board, int elem_num, float value)
{

	if (first_slide == NULL)
			return 0;
		
		slide_ptr = first_slide;
		assert (slide_ptr);
	
              	while ( slide_ptr != NULL )
               	{                         	
                		if ( slide_ptr->board == board && slide_ptr->elem_num == elem_num)
                            	{	
                            		slide_ptr->value = value;
                  			return 1;
                  		}
                 		slide_ptr = slide_ptr->next;

               	}

                 return 0;

}




   		
/***************************************************************************
* This function is used by "configuration.cpp" file in order to obtain the properties of
* button pointed by pointer "ptr". The string will be saved in "objString" variable.
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
bool
IOElementControl::ret_button_db_string (char objString[], Button *ptr)
{

  	
   if (ptr == NULL)
   	return false;

   	
   //cout <<"What is the current color now : " <<ptr->color<<endl;

   if (ptr->color == "" || ptr->color == " " || ptr->color == "0" || ptr->color == "1" )
   {
   	//cout <<"io_element_control.cpp: color is defaulted to grey for saving \n";
   	ptr->color = "grey" ;

   }
   // " name|type|board|elem_num|x|y|color|state "
   sprintf(objString, "%s|%s|%d|%d|%d|%d|%s|%d|%d|%d",
   		(ptr->name).c_str(),
   		(ptr->type).c_str(),
   		ptr->board,	
                ptr->elem_num,
                ptr->x,
                ptr->y,
                (ptr->color).c_str(),
                ptr->state,
                ptr->x2,
                ptr->y2 );

   return true;



}     	 	

/***************************************************************************
* This function is called by file_proc.tcl when we want to traverse the button database
* providing the "size" of database as an argument.
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_button_string (int size)
{

   //char objString[100];	
   //cout <<"io_element_control.cpp: bcount here is : "<<bcount<<endl;
   	
   if (size > bcount)
   	return '\0';

   Button *ptr = first_but;
   Button *temp = ptr;

   for (int i = 0; i < size; i++)
   {
   	temp = ptr;
   	if (ptr == NULL)
   		return '\0';
   		
     	ptr = ptr->next;

   }

   sprintf(result_string, "%s|%s|%d|%d|%d|%d|%s|%d|%d|%d",
   		(ptr->name).c_str(),
   		(ptr->type).c_str(),
   		ptr->board,	
                ptr->elem_num,
                ptr->x,
                ptr->y,
                (ptr->color).c_str(),
                ptr->state,
                ptr->x2,
                ptr->y2 );

   return result_string;

}     	




/***************************************************************************
* This function is used by "configuration.cpp" file in order to obtain the properties of
* slidebar pointed by pointer "ptr". The string will be saved in "objString" variable.
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/  	
bool
IOElementControl::ret_slide_db_string (char objString[], Slidebar *ptr)
{

		
   if (ptr == NULL)
   	return false;

   	
   if (ptr->color == "" || ptr->color == " " || ptr->color == "0" || ptr->color == "1" )
   {
   	//cout <<"io_element_control.cpp: color is defaulted to grey for saving \n";
   	ptr->color = "grey" ;

   }
   // " name|board|elem_num|x|y|value "
   sprintf(objString, "%s|%d|%d|%f|%d|%d|%s|%d|%d",
   		(ptr->name).c_str(),
   		ptr->board,	
                ptr->elem_num,
                ptr->value,
                ptr->x,
                ptr->y,
                (ptr->color).c_str(),
                ptr->x2,
                ptr->y2 );

   return true;

}     	 	




/***************************************************************************
* This function is called by file_proc.tcl when we want to traverse the slidebar database
* providing the "size" of database as an argument.
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_slidebar_string (int size)
{

   //char objString[100];	

   //cout <<"io_element_control.cpp: scount here is : "<<scount<<endl;
   	
   if (size > scount)
   	return '\0';

   Slidebar *ptr = first_slide;
   Slidebar *temp = ptr;

   for (int i = 0; i <= size; i++)
   {
   	temp = ptr;
   	if (ptr == NULL)
   		return '\0';
   		
     	ptr = ptr->next;

   }

   	
   // " name|board|elem_num|x|y|value "
   sprintf(result_string, "%s|%d|%d|%f|%d|%d|%s|%d|%d",
   		(temp->name).c_str(),
   		temp->board,	
                temp->elem_num,
                temp->value,
                temp->x,
                temp->y,
                (temp->color).c_str(),
                temp->x2,
                temp->y2 );

   return result_string;

}     	


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::clean_all_ioelem   ()
{

        // Delete all the output nodes first
	for(currDigIn = topdigitalInList.begin(); currDigIn != topdigitalInList.end(); ++currDigIn)
	       delete_output(currDigIn->next_out);

  	for(currSubDigIn = subdigitalInList.begin(); currSubDigIn != subdigitalInList.end(); ++currSubDigIn)
	   	delete_output(currSubDigIn->next_out);

        	for(currAnaIn = topanalogInList.begin(); currAnaIn != topanalogInList.end(); ++currAnaIn)
	     	delete_output(currAnaIn->next_out);
	
	for(currSubAnaIn = subanalogInList.begin(); currSubAnaIn != subanalogInList.end(); ++currSubAnaIn)
	     	delete_output(currSubAnaIn->next_out);

        	for(currAnaOut = topanalogOutList.begin(); currAnaOut != topanalogOutList.end(); ++currAnaOut)
	     	currAnaOut->out_string = "\0";
	     	
	     	
	// Delete the IO Element  	
	clean_db();
	
	// Clean up Button database
	
     	
	while (first_but != NULL)
	{
		but_ptr = first_but;
	        first_but = but_ptr->next;
	        delete but_ptr;
		
		bcount--;
	}
	
	first_but = NULL;
	but_ptr = NULL;
	//display_button_db();
	// Clean up Slidebar database
	
     	
	while (first_slide != NULL)
	{
		slide_ptr = first_slide;
	        first_slide = slide_ptr->next;
	        delete slide_ptr;
		
		scount--;
	}
	
	first_slide = NULL;
	slide_ptr = NULL;
	//display_slidebar_db();
		
	return 1;	     	
}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
char*
IOElementControl::get_button_connection(string name)
{


	if (first_but == NULL)
	{
  		sprintf(result_string, "%d", -1);
  		return result_string;
  	}	
		
	but_ptr = first_but;
	assert (but_ptr);
	
        while ( but_ptr != NULL )
        {                         	
        	if ( but_ptr->name == name)
               	{	
               		// set the new state
               		sprintf(result_string, "%d|%d", but_ptr->board, but_ptr->elem_num);                           	 	
                        return result_string;                                                 		
                }
                            	
                but_ptr = but_ptr->next;
  	}
  	
  	sprintf(result_string, "%d", -1);
  	return result_string;

  	
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_button_name(int board, int elem_num)
{
        if (first_but == NULL)
	{
  		sprintf(result_string, "%c", '\0');
  		return result_string;
  	}	
		
	but_ptr = first_but;
	assert (but_ptr);
	
        while ( but_ptr != NULL )
        {                         	
        	if ( but_ptr->board == board && but_ptr->elem_num == elem_num)
               	{	
               		// set the new state
               		sprintf(result_string, "%s", but_ptr->name.c_str());                           	 	
                        return result_string;                                                 		
                }
                            	
                but_ptr = but_ptr->next;
  	}
  	
 	
 	sprintf(result_string, "%c", '\0');
  	return result_string;

}
	
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_button_color_type(int board, int elem_num)
{
        if (first_but == NULL)
	{
  		sprintf(result_string, "%d", -1);
  		return result_string;
  	}	
		
	but_ptr = first_but;
	assert (but_ptr);
	
        while ( but_ptr != NULL )
        {                         	
        	if ( but_ptr->board == board && but_ptr->elem_num == elem_num)
               	{	
               		// set the new state
               		sprintf(result_string, "%s %s", but_ptr->color.c_str(), but_ptr->type.c_str());                           	 	
                        return result_string;                                                 		
                }
                            	
                but_ptr = but_ptr->next;
  	}
  	
 	
 	sprintf(result_string, "%d", -1);
  	return result_string;

}



/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
char*
IOElementControl::get_slide_connection(string name)
{


  	if (first_slide == NULL)
  	{
  		sprintf(result_string, "%d", -1);
  		//cout<<"io_element_control.cpp: Slidebar db is NULL "<<endl;
  		return result_string;
  	}
		
	slide_ptr = first_slide;
	assert (slide_ptr);
	
        while ( slide_ptr != NULL )
        {                         	
        	if ( slide_ptr->name == name)
               	{	
               		/*
               		// set the new state
               		cout<<"io_element_control.cpp: slide_ptr->name: "<<slide_ptr->name<<endl;
               		
               		cout<<"io_element_control.cpp: slide_ptr->board : "<<slide_ptr->board<<endl;
               		cout<<"io_element_control.cpp: slide_ptr->elem_num : "<<slide_ptr->elem_num<<endl;
               		
               		*/
               		sprintf(result_string, "%d|%d", slide_ptr->board, slide_ptr->elem_num);                           	 	
                        return result_string;                                                 		
                }
                            	
                slide_ptr = slide_ptr->next;
  	}
  	
  	
  	// if nothing found	
  	//cout<<"io_element_control.cpp: Can not find the slidebar with such name "<<endl;
  		
  	sprintf(result_string, "%d", -1);
  	return result_string;
  	
}

/*****************************************************************************
* Makes the two elements that are connected to switch inputs 49 and 50
* The outputs of the element are connected somewhere else by the user.
* Initializes the following:
*						1) element49 and element50
*						2) 
* Returns:
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::Detritus_make()
{
	digIterator it;
	
	Output_List	*out49;   		
	Output_List	*out50;   		
	int findElement	= -1;
	int surfVehicle = 1;
	int digAnalog 	= 1;
	int element_num	= 49;

	/* find first Detritus io_element */
	if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL ) {
		/* make an element */
		IOElement element49;
		element49.make(	surfVehicle, 
				digAnalog, 
				element_num,
				"Detritus", 
   			       "0:0:0:0",	
				0, 			/* default level 	*/
				1,			/* enable channel	*/
				0, 			/* auto_calibrate 	*/
				0,			/* enable_graphics 	*/
				0,			/* digital value 	*/
				0.0,			/* analog value 	*/
				0.0, 			/* analog raw 		*/
				0.0, 			/* analog offset 	*/
				0.0,			/* gain 		*/
				0.0,			/* max 		*/
				0.0,			/* min 		*/
				"none",			/* graphic type 	*/
				0,			/* color	 	*/
				0,			/* x 			*/
				0, 			/* y			*/
				0			/* no VGA		*/
			       );
		element49.next_out = NULL;
		
		if (ioElementControl.pushElement(element49) == false)
			return -1;		
	
	
		//topdigitalInList.push_back(element49);
 	
	
	}
			

	/* find 2nd Detritus io_element */
	element_num = 50;
	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL) {
		IOElement element50;
		element50.make(	surfVehicle, 
				digAnalog, 
				element_num,
				"Detritus", 
   			       "0:0:0:0",	
				0, 			/* default level 	*/
				1,			/* enable channel	*/
				0, 			/* auto_calibrate 	*/
				0,			/* enable_graphics 	*/
				0,			/* digital value 	*/
				0.0,			/* analog value 	*/
				0.0, 			/* analog raw 		*/
				0.0, 			/* analog offset 	*/
				0.0,			/* gain 		*/
				0.0,			/* max 		*/
				0.0,			/* min 		*/
				"none",			/* graphic type 	*/
			    	0,			/* color	    	*/
				0,			/* x 			*/
				0, 			/* y			*/
				0			/* no VGA		*/
			       );
		element50.next_out = NULL;
		
		
		if (ioElementControl.pushElement(element50) == false)
			return -1;		
		
		
	  	//topdigitalInList.push_back(element50);
 	
		
	}

	return 1;
}


/***************************************************************************
* Detritus_select()
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::Detritus_select(int selection)
{
	digIterator it;
	int surfVehicle = 1;
	int digAnalog 	= 1;
	int element_num	= 49;
	
	//cout <<"detritus_select : "<<detritus_select<<endl;
	
	//----------- if the user select "None" for Detritus -------------
	if (selection == 9)
	{
	        detritus_interlock = 0;  //used as a digital output bit for the relay in the console
	
		/* find first Detritus io_element */
		if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL)
		{	
			//cout <<"element is not made\n" ;
			return -1;				
		}
		else
		{	
			Output_List *ptr;
			for (ptr = it->next_out ; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 &&
				     ptr->out_elem_num >= 9 && ptr->out_elem_num <= 24 )
				{
					delete_single_output (element_num, ptr);
					set_out_string(it, it->next_out);
					break;
				}
			}
			
		}

			
		/* find 2nd Detritus io_element */
		element_num = 50;
		if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL)
		{
			//cout <<"cant create detritus for element 50";
			return -1;
		}
		else {
			
			Output_List *ptr;
			for (ptr = it->next_out ; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 &&
				     ptr->out_elem_num >= 9 && ptr->out_elem_num <= 24 )
				{
					delete_single_output (element_num, ptr);
					set_out_string(it, it->next_out);
					break;
				}
			}
			
			return 1;
		}
	
		return 1;
	}
	
	else detritus_interlock = 1; //used as a digital output bit for the relay in the console
	
	// ---------------------------------------------------------------
	
	// If the index is out of range, return
	if (selection < 1 || selection > 8) 
		return -1;

		
	
	/* find first Detritus io_element */
	if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL)
	{	
		//cout <<"Element 49 was not made\n" ;
		return -1;				
	}
	else {
		
		Output_List *ptr;
		Output_List *temp;
		Output_List *new_node49;
		
		// Create new node for Detritus
		new_node49 = new Output_List;
	        new_node49->next = NULL;
		new_node49->prev = NULL;
		new_node49->out_surveh = 0;	// vehicle
		new_node49->out_diganal = 1;	// digital
		new_node49->out_board = 0;		// gesout
		new_node49->out_elem_num = ((selection - 1) * 2) + 9;
		new_node49->out_digital_value = 0;
		new_node49->out_analog_value = -1;
			
		// If previous selection is none, then nothing to delete
		// This avoid deleting some other output other than detritus
		// output in element 49
		if (detritus_select != 9)
		{	
			// traverse all the output nodes
			for (ptr = it->next_out; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 && ptr->out_elem_num == ((detritus_select - 1) * 2) + 9 )
				{
					delete_single_output (element_num, ptr);
					break;
				}
			}
		
		}	
		
		Output_List *temp_prev;
		temp_prev = it->next_out;
			
		if (temp_prev == NULL)
			it->next_out = new_node49;
			
		else
		{
			for (temp = it->next_out; temp != NULL; temp = temp->next)
			{
				temp_prev = temp;
			}
		
			// Now append it at the very end
			temp_prev->next = new_node49;
		}	
	//}
		
		
		
		set_out_string(it, it->next_out);
	}

			
	/* find 2nd Detritus io_element */
	element_num = 50;
	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL)
	{
		//cout <<"cant create detritus for element 50";
		return -1;
	}
	else
	{
		Output_List *ptr;
		Output_List *temp;
		
		Output_List *new_node50;
		
		// Create new node for Detritus
		new_node50 = new Output_List;
	        new_node50->next = NULL;
		new_node50->prev = NULL;
		new_node50->out_surveh = 0;		// vehicle
		new_node50->out_diganal = 1;		// digital
		new_node50->out_board = 0;		// gesout
		new_node50->out_elem_num = ((selection * 2 ) - 1) + 9;
		new_node50->out_digital_value = 0;
		new_node50->out_analog_value = -1;
		
		// If previous selection is none, then nothing to delete
		// This avoid deleting some other output other than detritus
		// output in element 50
		if (detritus_select != 9)
		{	
			// traverse all the output nodes
			for (ptr = it->next_out; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 &&  ptr->out_elem_num == ((detritus_select * 2) - 1 ) + 9 )
				{
					delete_single_output (element_num, ptr);
				        break;
				}
			}
			
		}
		
		Output_List *temp_prev;
		temp_prev = it->next_out;
		
	
		if (temp_prev == NULL)
			it->next_out = new_node50;
		
		else
		{			
			for (temp = it->next_out; temp != NULL; temp = temp->next)
			{
				temp_prev = temp;
			}
		
			//cout<<"it->next_out->elem_num"<<it->next_out->out_elem_num<<endl;
			// Now append it at the very end
			temp_prev->next = new_node50;
	  	}
	
	  //	}
				
		set_out_string(it, it->next_out);
			
	
		// save the selection as global variable
		detritus_select = selection;	
		//cout <<"detritus_select : "<<detritus_select<<endl;
		
		return 1;
	}
	
	return 1;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
void 
IOElementControl::Detritus_initialize()
{
	/* initialize each structure */
	for (int i = 0; i < 16; i++) {
		Detritus[i].next = NULL;
		Detritus[i].prev = NULL;
		Detritus[i].out_surveh = 0;	/* vehicle */
		Detritus[i].out_diganal = 1;	/* digital */
		Detritus[i].out_board = 0;	/* gesout */
		Detritus[i].out_elem_num = i + 9;
		Detritus[i].out_digital_value = 0;
		Detritus[i].out_analog_value = -1;
	}

}




/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::get_graph_info(int index, char graph_string[] )
{
	subanalogInList[index].get_graph_info(graph_string);
	return 1;	

}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::setting_bar_detail (int elem_num,  float max, float min, float ave, float yrange, float rrange )
{            	
        	bar_detail[elem_num].min = min;
        	bar_detail[elem_num].max = max;
		bar_detail[elem_num].average = ave;
        	bar_detail[elem_num].yrange = yrange;
        	bar_detail[elem_num].rrange = rrange;
        	
  /*
   	cout<<"io_element_control.cpp: min = " <<bar_detail[elem_num].min <<"\n";
   	cout<<"io_element_control.cpp: max = " <<bar_detail[elem_num].max <<"\n";
   	cout<<"io_element_control.cpp: average = " <<bar_detail[elem_num].average <<"\n";
   	cout<<"io_element_control.cpp: yrange = " <<bar_detail[elem_num].yrange <<"\n";
   	cout<<"io_element_control.cpp: rrange = " <<bar_detail[elem_num].rrange <<"\n";
  */
   	
  	


        return 1;                                                  	

}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::getting_bar_detail (int elem_num,  char bar_string[] )
{
	sprintf (bar_string, "%d|%3.1f|%3.1f|%3.1f|%3.1f|%3.1f", 	
   	 		elem_num,
   	 		bar_detail[elem_num].max,
             			bar_detail[elem_num].min,
             			bar_detail[elem_num].average,
             			bar_detail[elem_num].yrange,
             			bar_detail[elem_num].rrange );

             return 1;
}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_element_name(int surveh, int diganal, int elem_num)
{

	anaIterator it;
	
	if ((it = getIOElement(surveh, diganal, elem_num, it)) == NULL)
	{
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	
	snprintf(result_string, 512, "%s", it->element_name_.c_str());
	return result_string;


}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_slidebar_name(int board, int elem_num)
{
        if (first_slide == NULL)
	{
  		sprintf(result_string, "%c", '\0');
  		return result_string;
  	}	
		
	slide_ptr = first_slide;
	assert (slide_ptr);
	
        while ( slide_ptr != NULL )
        {                         	
        	if ( slide_ptr->board == board && slide_ptr->elem_num == elem_num)
         	{	
               		// set the new state
              	sprintf(result_string, "%s", slide_ptr->name.c_str());                           	 	
              	return result_string;                                                 		
          	}
                            	
                slide_ptr = slide_ptr->next;
         }
  	
 	sprintf(result_string, "%c", '\0');
  	return result_string;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_bname(int index)
{
	Button *temp;
        if (first_but == NULL)
	{
  		sprintf(result_string, "%d", -1);
  		return result_string;
  	}	
		
  	int i = 0;
	temp = first_but;
	assert (temp);
	
        while ( temp != NULL && i < index )
        {                         	         	
                temp = temp->next;
                i++;
  	}
  	     	 	
  	assert(temp);
  	
 	sprintf(result_string, "%s", temp->name.c_str());
  	return result_string;

}
	
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_sname(int index)
{
	Slidebar *temp;
        if (first_slide == NULL)
	{
  		sprintf(result_string, "%d", -1);
  		return result_string;
  	}	
		
  	int i = 0;
	temp = first_slide;
	assert (temp);
	
        while ( temp != NULL && i < index )
        {                         	         	
                temp = temp->next;
                i++;
  	}
  	     	 	
  	assert(temp);
  	
 	sprintf(result_string, "%s", temp->name.c_str());
  	return result_string;

}
	

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::ret_subana_elem_num(int index)
{
	if (subanalogInList[index].graphics_.type_ == "Bar" || subanalogInList[index].graphics_.type_ == "bar" ||
	subanalogInList[index].graphics_.type2_ == "Bar" || subanalogInList[index].graphics_.type2_ == "bar" )
		return subanalogInList[index].num();
	else
		return -1;
}

/**************************** AUTOCALIBRATE functions ****************/
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int	
IOElementControl::autoCalibrateMax(int surfVeh, int digAnalog, int elem_num, 
				   float max)
{
	anaIterator it;	
	float	voltRead;
	float	raw;
	int 	type;

      //startConversion(ioFD);


	// find the io_element
	if ((it = getIOElement(surfVeh, digAnalog, elem_num, it)) == NULL ) {
		return -1;
	}
	type = it->getIOtype();
	
	// check if autocalibrate is enabled
	if (!it->auto_calibrate_enable_) {
		return -2;
	}

	// set the max value
	it->max_ = max;
	switch (type) {

	case topAnalogIn:
		// read the max voltage
		//readVolt(ioFD, elem_num, voltRead, raw);
		voltRead = current_adc[elem_num - 1].volt;
		raw = current_adc[elem_num - 1].intVolt;	
		if (it->tmpMax < voltRead)
			it->tmpMax = voltRead;
		break;
			
      	case subAnalogIn:
		voltRead = it->analog_raw_;
		if (it->tmpMax < voltRead)
			it->tmpMax = voltRead;
		        break;
		
	case topAnalogOut:
	        voltRead = it->analog_raw_;
		if (it->tmpMax < voltRead)
			it->tmpMax = voltRead;
		        break;
		
	
	default:
		return -1;
		break;
	}
	return 1;
}
	
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int	
IOElementControl::autoCalibrateMin(int surfVeh, int digAnalog, int elem_num, 
				   float min)

{

	
	anaIterator it;	
	float	voltRead;
	float	raw;
 	float   dividend;
	int 	type;      
 
      	//startConversion(ioFD);

	// find the io_element
	if ((it = getIOElement(surfVeh, digAnalog, elem_num, it)) == NULL ) {
		return -1;
	}
	type = it->getIOtype();
	
	// check if autocalibrate is enabled
	if (!it->auto_calibrate_enable_) {
		return -2;
	}

	// set the min value
	it->min_ = min;

	switch (type) {

	case topAnalogIn:
		voltRead = current_adc[elem_num - 1].volt;
		raw = current_adc[elem_num - 1].intVolt;	
		break;	
      	case subAnalogIn:
		voltRead = it->analog_raw_;
		break;
	case topAnalogOut:
	        voltRead = it->analog_raw_;
		break;
		
	default:
		return -1;
		break;
	}
	

	if (it->tmpMin > voltRead)
		it->tmpMin = voltRead;
	dividend = it->tmpMax - it->tmpMin;

	if (dividend == 0)           	// we do not want to divide with 0
		dividend += 0.01;	
	it->analog_gain_ = ((it->max_)-(it->min_)) / dividend; 
	it->analog_offset_ = -(((it->analog_gain_) * (it->tmpMin)) - (it->min_));
	it->usedAutoCalibrate = 1;

	
	return 1;
}


/***************************************************************************
*  This function is called by the telemetry to update 
*  the vehicle analog values 
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
float
IOElementControl::updateVehAnalog(int elem_num, float analog_val)
{
   /* surfVehicle: 	0 - vehicle
    * 		   	1 - surface
    * digitalAnalog:	0 - Analog
    * 			1 - digital
    */
 
	anaIterator it;	
        float applied;
	
	// find the io_element
	if ((it = getIOElement(0, 0, elem_num, it)) == NULL ) {
		return -1;
	}
	else if (it->getIOtype() != subAnalogIn) {
		return -1;
	}

	assert(it);	
	it->updateAnalogRaw(analog_val);
	applied = it->analog_gain_ * analog_val + it->analog_offset_;
	
	return applied;
}



/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_xy_pos(int elem_num, int screen)
{

	anaIterator it;
	
	if ((it = getIOElement(0, 0, elem_num, it)) == NULL)
	{
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	
	if (screen == 1)
		snprintf(result_string, 512, "%d %d", it->graphics_.x_, it->graphics_.y_);
	else
		snprintf(result_string, 512, "%d %d", it->graphics_.x2_, it->graphics_.y2_);



	return result_string;


}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/	
char*	
IOElementControl::get_master_feedback_arm() 
{
	anaIterator it;
	char temp[20];
	
      	/************* shoulder **********************/ 
	memset(result_string, 0, 512);	
	if ((it = getIOElement(1, 0, vehicle.arm.command_shoulder_channel_top, 
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.arm.master_shoulder = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);

		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.arm.feedback_shoulder);
		strncat(result_string, temp, 512);

	}

	/************* swing ****************/
	if ((it = getIOElement(1, 0, vehicle.arm.command_swing_channel_top, 
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.arm.master_swing = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);

		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.arm.feedback_swing);
		strncat(result_string, temp, 512);
	
	}


	/************* elbow ****************/
	if ((it = getIOElement(1, 0, vehicle.arm.command_elbow_channel_top, 
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.arm.master_elbow = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);
		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.arm.feedback_elbow);
		strncat(result_string, temp, 512);
	
	}
	

	/************* pitch ****************/
	if ((it = getIOElement(1, 0, vehicle.arm.command_pitch_channel_top, 
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.arm.master_pitch = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);
		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.arm.feedback_pitch);
		strncat(result_string, temp, 512);

	}
	

	/************* yaw ****************/
	if ((it = getIOElement(1, 0, vehicle.arm.command_yaw_channel_top, 
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.arm.master_yaw = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);
		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.arm.feedback_yaw);
		strncat(result_string, temp, 512);
	}
	

	return result_string;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*	
IOElementControl::get_master_feedback_cam()
{
	anaIterator it;
	char temp[20];


  	/************* shoulder **********************/
	memset(result_string, 0, 512);	
	if ((it = getIOElement(1, 0, vehicle.camera.command_shoulder_channel_top,
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.camera.master_shoulder = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);
	
		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.camera.feedback_shoulder);
		strncat(result_string, temp, 512);
	
	}

	/************* pan ****************/
	if ((it = getIOElement(1, 0, vehicle.camera.command_pan_channel_top,
			       it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;
		
	}
	else {
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
    		vehicle.camera.master_pan = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_);	
		strncat(result_string, temp, 512);

		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f|\0", vehicle.camera.feedback_pan);
		strncat(result_string, temp, 512);
	
	}

	
	/************* tilt ****************/
	
	if ((it = getIOElement(1, 0, vehicle.camera.command_tilt_channel_top, it)) == NULL) {
		snprintf(result_string, 512, "%c", '\0');
		return result_string;		
	}
	else {
	
	        /*
		cout << "===========================================" << endl;
		cout << "master: name " << it->element_name_ << endl;
		cout << "master: num " << it->element_num_ << endl;
    		cout << "master: raw: " << it->analog_raw_ << endl;
    		cout << "master: gain : " << it->analog_gain_ << endl;
    		cout << "master: offset: " << it->analog_offset_ << endl;
		cout << "master: analog: " << it->analog_value_ << endl;    	
	        */
	
		memset(temp, 0, 20);
		it->analog_value_ = it->analog_raw_ * it->analog_gain_ +
				    it->analog_offset_;	
				
		
    		vehicle.camera.master_tilt = it->analog_value_;
		snprintf(temp, 20, "%4.3f|\0", it->analog_value_ );	
		strncat(result_string, temp, 512);
	
		memset(temp, 0, 20);
		snprintf(temp, 20, "%4.3f\0", vehicle.camera.feedback_tilt);
		strncat(result_string, temp, 512);
	
		
	}
	
	

	//cout << "masterfeedback cam string: " << result_string << endl;

	return result_string;

	
}


/*****************************************************************************
* Makes the two elements that are hard coded to the tools. Elemnet 69 and 70 
* are the switch inputs
* Initializes the following:
*						1)element69 and element 70 
*						2) 
* Returns:
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::Tool_make()
{
	digIterator it;
	
	int findElement	= -1;
	int surfVehicle = 1;
	int digAnalog 	= 1;
	int element_num	= 69;

	/* find first Tool io_element */
	if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL ) {
		/* make an element */
		IOElement element69;
		element69.make(	surfVehicle,
				digAnalog,
				element_num,
				"Tool",
   			       "0:0:0:0",	
				0, 			/* default level 	*/
				1,			/* enable channel	*/
				0, 			/* auto_calibrate 	*/
				0,			/* enable_graphics 	*/
				0,			/* digital value 	*/
				0.0,			/* analog value 	*/
				0.0, 			/* analog raw 		*/
				0.0, 			/* analog offset 	*/
				0.0,			/* gain 		*/
				0.0,			/* max 		*/
				0.0,			/* min 		*/
				"none",			/* graphic type 	*/
				0,			/* color	 	*/
				0,			/* x 			*/
				0, 			/* y			*/
				0			/* no VGA		*/
			       );
		element69.next_out = NULL;
		/*
		if (ioElementControl.pushElement(element69) == false)
			return -1;		
		  */
		topdigitalInList.push_back(element69);
 	
	}
			

	/* find 2nd Tool io_element */
	element_num = 70;
	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL) {
		IOElement element70;
		element70.make(	surfVehicle,
				digAnalog,
				element_num,
				"Tool",
   			       "0:0:0:0",	
				0, 			/* default level 	*/
				1,			/* enable channel	*/
				0, 			/* auto_calibrate 	*/
				0,			/* enable_graphics 	*/
				0,			/* digital value 	*/
				0.0,			/* analog value 	*/
				0.0, 			/* analog raw 		*/
				0.0, 			/* analog offset 	*/
				0.0,			/* gain 		*/
				0.0,			/* max 		*/
				0.0,			/* min 		*/
				"none",			/* graphic type 	*/
			    	0,			/* color	    	*/
				0,			/* x 			*/
				0, 			/* y			*/
				0			/* no VGA		*/
			       );
		element70.next_out = NULL;
		
		/*
		if (ioElementControl.pushElement(element70) == false)
			return -1;		
		  */
		topdigitalInList.push_back(element70);
 	
		
			
	}
	
	return 1;

}




/*********************************** Tool_select() ******************************/
/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::Tool_select(int selection)
{
	digIterator it;
	int out_elem_num;
	int new_sel;
	int surfVehicle = 1;
	int digAnalog 	= 1;
	int element_num	= 69;

		
	//cout <<"tool_select : "<<tool_select<<endl;
	
	//----------- if the user select "None" for Tool -------------
	if (selection == 5)
	{
		tool_interlock = 0;	
		/* find first Tool io_element */
		if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL)
		{	
			//cout <<"element is not made\n" ;
			return -1;				
		}
		else
		{	
			Output_List *ptr;
			for (ptr = it->next_out ; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 &&
				   ( ptr->out_elem_num == 29 || ptr->out_elem_num == 31 ||
				     ptr->out_elem_num == 25 || ptr->out_elem_num == 2 ))
				{
					delete_single_output (element_num, ptr);
					set_out_string(it, it->next_out);
					break;
				}
			}
			
		}

			
		/* find 2nd Tool io_element */
		element_num = 70;
		
		if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL)
		{
			//cout <<"cant create tool for element 70";
			return -1;
		}
		else {
			
			Output_List *ptr;
			for (ptr = it->next_out ; ptr != NULL; ptr = ptr->next)
			{
			
				if ( ptr->out_board == 0 &&
				   ( ptr->out_elem_num == 30 || ptr->out_elem_num == 32 ||
				     ptr->out_elem_num == 26 || ptr->out_elem_num == 1 ))
				{
					delete_single_output (element_num, ptr);
					set_out_string(it, it->next_out);
					break;
				}
			}
			
			return 1;
		}
	
		return 1;
	}
	else tool_interlock = 1;
	// ---------------------------------------------------------------
	// If user wants to create a new output node
	//----------------------------------------------------------------
	
	// If the index is out of range, return
	if (selection < 1 || selection > 4)
		return -1;

		
	
	/* find first Tool io_element */
	if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL)
	{	
		//cout <<"Element 69 was not made\n" ;
		return -1;				
	}
	else {
		
		Output_List *ptr;
		Output_List *temp;
		Output_List *new_node69;
				
		if (tool_select == 1)
			out_elem_num = 29;
		else if (tool_select == 2)
			out_elem_num = 31;
		else if (tool_select == 3)
			out_elem_num = 25;
		else if (tool_select == 4)
			out_elem_num = 2;
			
			
		// for the new selection
		
		if (selection == 1)
			new_sel = 29;
		else if (selection == 2)
			new_sel = 31;
		else if (selection == 3)
			new_sel = 25;
		else if (selection == 4)
			new_sel = 2;
			
	
		// Create new node for Tool
		new_node69 = new Output_List;
	        new_node69->next = NULL;
		new_node69->prev = NULL;
		new_node69->out_surveh = 0;	// vehicle
		new_node69->out_diganal = 1;	// digital
		new_node69->out_board = 0;		// gesout
		new_node69->out_elem_num = new_sel;
		new_node69->out_digital_value = 0;
		new_node69->out_analog_value = -1;
			
		// If previous selection is none, then nothing to delete
		// This avoid deleting some other output other than tool
		// output in element 69
		if (tool_select != 5)
		{	
	
			
			// traverse all the output nodes
			for (ptr = it->next_out; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 && ptr->out_elem_num == out_elem_num )
				{
					delete_single_output (element_num, ptr);
					break;
				}
			}
		
		}	
		
		Output_List *temp_prev;
		temp_prev = it->next_out;
			
		if (temp_prev == NULL)
			it->next_out = new_node69;
			
		else
		{
			for (temp = it->next_out; temp != NULL; temp = temp->next)
			{
				temp_prev = temp;
			}
		
			// Now append it at the very end
			temp_prev->next = new_node69;
		}	
		
		set_out_string(it, it->next_out);
	}

			
	/* find 2nd Tool io_element */
	element_num = 70;
	
	if (tool_select == 1)
		out_elem_num = 30;
	else if (tool_select == 2)
		out_elem_num = 32;
	else if (tool_select == 3)
		out_elem_num = 26;
	else if (tool_select == 4)
		out_elem_num = 1;
			

	// for the new selection
	
	if (selection == 1)
		new_sel = 30;
	else if (selection == 2)
		new_sel = 32;
	else if (selection == 3)
		new_sel = 26;
	else if (selection == 4)
		new_sel = 1;
			

	if ((it = getIOElement(surfVehicle, digAnalog, element_num, it)) == NULL)
	{
		//cout <<"cant create tool for element 70";
		return -1;
	}
	else
	{
		Output_List *ptr;
		Output_List *temp;
		
		Output_List *new_node70;
		
		// Create new node for Tool
		new_node70 = new Output_List;
	        new_node70->next = NULL;
		new_node70->prev = NULL;
		new_node70->out_surveh = 0;		// vehicle
		new_node70->out_diganal = 1;		// digital
		new_node70->out_board = 0;		// gesout
		new_node70->out_elem_num = new_sel;
		new_node70->out_digital_value = 0;
		new_node70->out_analog_value = -1;
		
		// If previous selection is none, then nothing to delete
		// This avoid deleting some other output other than tool
		// output in element 70
		if (tool_select != 5)
		{	
			
			// traverse all the output nodes
			for (ptr = it->next_out; ptr != NULL; ptr = ptr->next)
			{
				if ( ptr->out_board == 0 &&  ptr->out_elem_num == out_elem_num )
				{
					delete_single_output (element_num, ptr);
				        break;
				}
			}
			
		}
		
		Output_List *temp_prev;
		temp_prev = it->next_out;
		
	
		if (temp_prev == NULL)
			it->next_out = new_node70;
		
		else
		{			
			for (temp = it->next_out; temp != NULL; temp = temp->next)
			{
				temp_prev = temp;
			}
		
			//cout<<"it->next_out->elem_num"<<it->next_out->out_elem_num<<endl;
			// Now append it at the very end
			temp_prev->next = new_node70;
	  	}
	
	  		
		set_out_string(it, it->next_out);
			
	
		// save the selection as global variable
		tool_select = selection;	
		//cout <<"tool_select : "<<tool_select<<endl;
		
		return 1;
	}
	
	return 1;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
void
IOElementControl::Tool_initialize()
{
	/* initialize each structure */
	for (int i = 0; i < 16; i++) {
		Tool[i].next = NULL;
		Tool[i].prev = NULL;
		Tool[i].out_surveh = 0;	/* vehicle */
		Tool[i].out_diganal = 1;	/* digital */
		Tool[i].out_board = 0;	/* gesout */
		Tool[i].out_digital_value = 0;
		Tool[i].out_analog_value = -1;
		
	}
	
	        Tool[0].out_elem_num = 29;
		Tool[1].out_elem_num = 30;
		Tool[2].out_elem_num = 31;
		Tool[3].out_elem_num = 32;
		Tool[4].out_elem_num = 25;
		Tool[5].out_elem_num = 26;		
		Tool[6].out_elem_num = 1;
		Tool[7].out_elem_num = 2;
		
}



/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int IOElementControl::send_bottom_analog_down()
{
	
	anaIterator it;
	
	for(int i = 0; i < subanalogInList.size(); i++)
		{
	       	it = &subanalogInList[i];
		
		memset(result_string, 0, 512);
	 	snprintf (result_string, 512, "%d|%d|%4.3f|%4.3f\n",
	 		IN_ANALOG_GAINOFF, it->element_num_, it->analog_gain_, it->analog_offset_);
	 		 		
	 	//cout <<"result_string : "<<result_string<<endl;
	 	tty_send_request(result_string);
		}
	return 1;
}



/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int IOElementControl::get_auto_head_status()
{
    digIterator it;  	
    int elem_num = vehicle.autopilot.autoHead_ch;

    if ((it = getIOElement(1, 1, elem_num, it)) == NULL) return -1;		
	
    int status = it->digital_value_ ;
    return status;
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int IOElementControl::get_auto_depth_status()
{
    digIterator it;  	
    int elem_num = vehicle.autopilot.autoDepth_ch;

    if ((it = getIOElement(1, 1, elem_num, it)) == NULL) return -1;		
	
    int status = it->digital_value_ ;
    return status;
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int IOElementControl::get_auto_altitude_status()
{
    digIterator it;  	
    int elem_num = vehicle.autopilot.autoAltitude_ch;

    if ((it = getIOElement(1, 1, elem_num, it)) == NULL) return -1;		
	
    int status = it->digital_value_ ;
    return status;
}

/***************************************************************************
* This will be called from telemetry.cpp, where we get
* the "raw" values for depth and then update it here by
* multiplying it with gain and plus offset .
* The value returned from here will be then set to
* the curr_depth variable in vehicle class
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
float IOElementControl::update_depth_value(float raw)
{
 	anaIterator it;
 	
    	if ((it = getIOElement(0, 0, 43 , it)) == NULL)	return -1;		
	
    	float depth = it->analog_raw_ * it->analog_gain_ + it->analog_offset_;	                        	
    	return depth;                                      	                     		
}

/***************************************************************************
* This function is called when we want to deal with cycling the
* software enable on and off.
* if the software enable is On, then we want to send down 0 as the "SET_ARM_ENABLE"
* commmand to the sub to turn it off. No matter what the hardware/master switch is
* in On status or not
* if the software enable is turned on, we want to check what the status of the
* hardware/master switch, if they're both On, then we will send down 1 as  the
* "SET_ARM_ENABLE" command to the sub. But if the hardware switch is still Off when
* the software is on, then we do not do anything here. Therefore, the arm itself
* will still be disabled
* Note : for Hardware/ Master cycling, the error checking is done in function
* "send_output_down" that' is responsible for sending down digital / analog values
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int IOElementControl::switch_arm_enable(int status)
{
 	digIterator it;
 	
    	if ((it = getIOElement(1, 1, 40 , it)) == NULL) return -1;		
	
	if (status == 0 )
		{
	 	extern int ack_arm_enable;
		int loop_timeout = 0;
		ack_arm_enable = 0;

	 	vehicle.arm.arm_enable = 0;
	        it->enable_channel_ = 0;	
	        snprintf(result_string, 512, "%d|%d\n", SET_ARM_ENABLE, 0);
    		tty_send_request(result_string);
    		usleep(400000);
		cout << "io_element_control.cpp : Ack Arm Enable" << ack_arm_enable << endl;
		while(ack_arm_enable == 0)
		   	{
		   	tty_send_request(result_string);
		   	usleep(400000);
		   	cout << "io_elements_control.cpp : Ack Arm Enable" << ack_arm_enable << endl;
		   	loop_timeout ++;
		   	if (loop_timeout == 2)
   				{
		   		alarm_obj.set_other_alarm(30); //generate alarm
   				ack_arm_enable = 2;
		   		}
			}
    		// Turn off the control for arm on the sub, so we dont have
    		// to wait for the change in polling (send_output_down () )
    		memset(result_string, 0, 512);
    		snprintf(result_string, 512, "%d|%d|%d\n", 0, 8, 0);
    		tty_send_request(result_string);
		}
	else
		{
		vehicle.arm.arm_enable = 1;
	        it->enable_channel_ = 1;
	
	        // if the control switch is on, the tell the sub to turn on the
	        // arm right away
	
	        int digital = !topDigitalChannel[40];
	        //cout <<"io_element_control.cpp : digital value here : "<<digital<<endl;
	
	
	        if (digital == 1)
	        	{
	        	extern int ack_arm_enable;
			int loop_timeout = 0;
			ack_arm_enable = 0;
	    		
	    		snprintf(result_string, 512, "%d|%d\n", SET_ARM_ENABLE, 1);
    			tty_send_request(result_string);
    		        usleep(400000);
			cout << "io_element_control.cpp : Ack Arm Enable" << ack_arm_enable << endl;
			while(ack_arm_enable == 0)
			   	{
		   		tty_send_request(result_string);
			   	usleep(400000);
			   	cout << "io_elements_control.cpp : Ack Arm Enable" << ack_arm_enable << endl;
			   	loop_timeout ++;
		   		if (loop_timeout == 2)
	   				{
			   		alarm_obj.set_other_alarm(30); //generate alarm
   					ack_arm_enable = 2;
		   			}
				}
// Command : send_output_down( int surfVehicle, int digAnalog, int element_num, int digitalVal, float analogVal)
                      	send_output_down( 1, 1, 40, 1, 0);
    		 } 	// end  if(it->digital_value_ == 1)
    		
	 	
	}  	// end else
		
 	
	
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_sit_camera_angle()
{
	
	float pan, tilt;
	float raw;
	float gain;
	float offset;
	float max, min;
	
	
	readVoltage(0, 0, 19, pan, raw, gain,offset, max, min);  	
	readVoltage(0, 0, 20, tilt, raw, gain,offset, max, min);
	
	
	snprintf(result_string, 512, "%4.1f|%4.1f", pan, tilt);
	

	return result_string;
	
}



/***************************************************************************
* Returns the calculated analog value
* (gain and offset are applied already)
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
float
IOElementControl::get_analog_value(int surveh, int elem_num)
{
	float analog_value;
	float raw;
	float gain;
	float offset;
	float max, min;
	
	
	readVoltage(surveh, 0, elem_num, analog_value, raw, gain,offset, max, min);
	
	return analog_value;
	
}


// get any digital values



/***************************************************************************
*--------------This function can be taken out later -----------------------
* because the function get_digital_value from commands.c read straight from
* the function readFromChannel in this file.
* so we do not need this anymore, especially because the it->digital_value
* is only updated when we have telemetry connection
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::get_digital_value(int surveh, int elem_num)
{
	digIterator it;	

	if ((it = getIOElement(surveh, 1, elem_num, it)) != NULL)
		return it->digital_value_;
	return -1;	
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::get_overlay_channel(string name)
{
	anaIterator it;

        for(int i = 0; i < subanalogInList.size(); i++) {
	      	if (subanalogInList[i].element_name_ == name)
	      	{
		 	it = &subanalogInList[i];
		  	return it->element_num_;
	      	}
  	}
  	
  	return -1;
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_button_pos(int board, int elem_num, int screen)
{
	//cout <<"io_element_control: get button pos on screen : "<<screen<<endl;
        if (first_but == NULL)
	{
  		sprintf(result_string, "%c", '\0');
  		return result_string;
  	}	
		
	but_ptr = first_but;
	assert (but_ptr);
	
        while ( but_ptr != NULL )
        {                         	
        	if ( but_ptr->board == board && but_ptr->elem_num == elem_num)
               	{	
               		
               		// Screen 1
               		if (screen == 1)
               			sprintf(result_string, "%d %d", but_ptr->x, but_ptr->y);                           	 	
                        else
                        	sprintf(result_string, "%d %d", but_ptr->x2, but_ptr->y2);

                        return result_string;                                                 		
                }
                            	
                but_ptr = but_ptr->next;
  	}
  	
 	
 	sprintf(result_string, "%c", '\0');
  	return result_string;

}
	

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_slidebar_pos(int elem_num, int screen)
{
	//cout <<"io_element_control: get slidebar pos on screen : "<<screen<<endl;
        if (first_slide == NULL)
	{
  		sprintf(result_string, "%c", '\0');
  		return result_string;
  	}	
		
	slide_ptr = first_slide;
	assert (slide_ptr);
	
        while ( slide_ptr != NULL )
        {                         	
        	if (slide_ptr->board == 2 && slide_ptr->elem_num == elem_num)
               	{	
               		
               		// Screen 1
               		if (screen == 1)
               			sprintf(result_string, "%d %d", slide_ptr->x, slide_ptr->y);                           	 	
                        else
                        	sprintf(result_string, "%d %d", slide_ptr->x2, slide_ptr->y2);

                        return result_string;                                                 		
                }
                            	
                slide_ptr = slide_ptr->next;
  	}
  	
 	
 	sprintf(result_string, "%c", '\0');
  	return result_string;

}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::initializeLookup()
{
   anaIterator it;
	
   /* foreaft */
   if((it = getIOElement(1, 0, vehicle.autopilot.foreaft_ch, it)) == NULL)
      return -1;
   initializeLookupTable(1, vehicle.teleos.kf1_foreaft, 5.00, 
		         vehicle.teleos.kf2_foreaft, 
			 vehicle.teleos.db_foreaft, 
			 vehicle.teleos.st_foreaft); 
   /* turns */
   if((it = getIOElement(1, 0, vehicle.autopilot.turns_ch, it)) == NULL)
      return -1;
   initializeLookupTable(2, vehicle.teleos.kf1_turns, 5.00, 
		         vehicle.teleos.kf2_turns,
			 vehicle.teleos.db_turns,
			 vehicle.teleos.st_turns); 

   /* lateral */
   if((it = getIOElement(1, 0, vehicle.autopilot.lateral, it)) == NULL)
      return -1;
   initializeLookupTable(3, vehicle.teleos.kf1_lateral, 5.00, 
		         vehicle.teleos.kf2_lateral,
			 vehicle.teleos.db_lateral,
			 vehicle.teleos.st_lateral); 

   /* vertical */
   if((it = getIOElement(1, 0, vehicle.autopilot.vertical, it)) == NULL)
      return -1;
   initializeLookupTable(4, vehicle.teleos.kf1_vertical, 5.00, 
		         vehicle.teleos.kf2_vertical,
			 vehicle.teleos.db_vertical,
			 vehicle.teleos.st_vertical); 

   return 1;
}


/*****************************************************************************
*Makes the elements for the ADC inputs that monitor the DAC outputs on the sub.
*There are 16 inputs hardwired to each of the two DAC output boards.
* Constructor - initializes the following:
*						1) 
*						2) 
* Returns:
*
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/

int
IOElementControl::subout_make()
{
	anaIterator it;
	   		
	int findElement	= -1;
	int surfVehicle 	= 0;	// sub
	int digAnalog 	= 0;         	// analog
	
	for (int element_num = 49; element_num <= 64; element_num++)
	{
		if ((it = getIOElement(surfVehicle,digAnalog, element_num, it)) == NULL )
		{
		
			char temp[100];
			snprintf (temp, 100, "DAC %d", element_num - 48);
			string name(temp);
		
			/* make an element */
			IOElement subout_element;
			subout_element.make(	surfVehicle,
				digAnalog,
				element_num,
				name,
   			      	 "0:0:0:0",	
				0, 			/* default level 	*/
				1,			/* enable channel	*/
				0, 			/* auto_calibrate 	*/
				0,			/* enable_graphics 	*/
				0,			/* digital value 	*/
				0.0,			/* analog value 	*/
				0.0, 			/* analog raw 		*/
				0.0, 			/* analog offset 	*/
				0.0,			/* gain 		*/
				0.0,			/* max 		*/
				0.0,			/* min 		*/
				"none",			/* graphic type 	*/
				0,			/* color	 	*/
				0,			/* x 			*/
				0, 			/* y			*/
				0			/* no VGA		*/
			       );
			
			subout_element.next_out = NULL;
		
			if (ioElementControl.pushElement(subout_element) == false)
				return -1;		

				
			//cout <<"io_element_control.cpp: succeed creating sub output channel "<<element_num<<endl;
		                 //cout <<"name : "<<name<<endl;
		
		}	// end if
	
	}  	// end for loop

	return 1;
}

/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::delete_all_buttons()
{
	Button *ptr;
	Button *temp;
	
	//cout <<"Entering Button db deletion "<<endl;
	if (first_but == NULL)
	{
		//cout<<"io_element_control.cpp: No button to be deleted \n";
		return 1;
	}
	
	
	ptr = first_but;
	        	
 	while ( ptr != NULL )
  	{
               	temp = ptr;	
   		ptr = ptr->next;
                delete temp;
   		
 	}

 	first_but = NULL;
 	but_ptr = NULL;
 	bcount = 0;
 	
 	//cout <<"io_element_control.cpp : Done Cleaning Up Button DB\n";
 	return 1;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
int
IOElementControl::delete_all_slidebars()
{
	Slidebar *ptr;
	Slidebar *temp;
	
	//cout <<"Entering Slidebar db deletion "<<endl;
	if (first_slide == NULL)
	{
		//cout<<"io_element_control.cpp: No slidebar to be deleted \n";
		return 1;
	}
	
	
	ptr = first_slide;
	        	
 	while ( ptr != NULL )
  	{
               	temp = ptr;	
   		ptr = ptr->next;
                delete temp;
   		
 	}

 	first_slide = NULL;
 	slide_ptr = NULL;
 	scount = 0;
 	
 	//cout <<"io_element_control.cpp : Done Cleaning Up Slidebar DB\n";
 	return 1;

}


/***************************************************************************
* Initializes the following:
*						1) 
*						2) 
* Returns: 
* 
* Modified Last By:
* Date Modified:
* Modification:
******************************************************************************/
char*
IOElementControl::get_io_connection(string name)
{

	ana_out_iterator it;

             for (int i = 1; i <= 4; i++)
             {
             	if ((it = getIOElement(1, 3, i, it)) != NULL)
		{
			if (it->element_name_ == name)
             		{                    			
             			snprintf (result_string, 100,  "%d %d",  3 , it->element_num_);
             			return result_string;
             			
             		}      	// end nested if
             	}      	// end if             		
	}       	// end for loop
	
	snprintf (result_string, 100,  "%d" ,-1);
	return result_string;
	
}      	// end get_io_connection(name)
