// ============================================================================
//
// = CONTEXT
//    TANGO Project - SCPI KeithleySCPIProtocol Support Library
//
// = FILENAME
//    KeithleySCPIProtocol.cpp
//
// = AUTHOR
//    X. Elattaoui
//
// ============================================================================

// ============================================================================
// DEPENDENCIES
// ============================================================================
#include <iostream>
#include <sstream>
#include <string>
#include <Xstring.h>
#ifndef WIN32
# include <unistd.h>
#endif
#include "KeithleySCPIProtocol.h"
#include "TangoGpibLink.h"

// ============================================================================
// KeithleySCPIProtocol::KeithleySCPIProtocol
// ============================================================================
KeithleySCPIProtocol::KeithleySCPIProtocol (std::string& gpib_device_name)
:	ElectrometerProtocol(),
	isDiffSuportedMode(false),
	trigCountStr("")
{
	std::cout << "KeithleySCPIProtocol::KeithleySCPIProtocol <-" << std::endl;

  _commDevName = gpib_device_name;

	std::cout << "KeithleySCPIProtocol::KeithleySCPIProtocol ->" << std::endl;
}

// ============================================================================
// KeithleySCPIProtocol::~KeithleySCPIProtocol
// ============================================================================
KeithleySCPIProtocol::~KeithleySCPIProtocol (void)
{
	std::cout << "KeithleySCPIProtocol::~KeithleySCPIProtocol <-" << std::endl;

	std::cout << "KeithleySCPIProtocol::~KeithleySCPIProtocol ->" << std::endl;
}

// ============================================================================
// KeithleySCPIProtocol::build_communicationLink
// ============================================================================
bool KeithleySCPIProtocol::build_communicationLink()
{
  if (_commDevName.empty())
    return false;

	try
	{
		_communication_link = new TangoGpibLink (_commDevName);
	}
	catch(...)
	{
		if( _communication_link )
		{
			delete _communication_link;
			_communication_link = 0;
		}
		return false;
	}

  if (!_communication_link)
    return false;

	try
	{
		//- configure tthe SCPI Keithley device
		std::string cmd_to_send("");
		//- Select reading only
		cmd_to_send = "FORM:ELEM READ";
		_communication_link->write(cmd_to_send);
		//- Select control source : IMMediate
		cmd_to_send = "ARM:SOUR IMM";
		_communication_link->write(cmd_to_send);
		//- Set measure count
		cmd_to_send = "ARM:COUNT 1";
		_communication_link->write(cmd_to_send);
	}
	catch(...)
	{
		if( _communication_link )
		{
			delete _communication_link;
			_communication_link = 0;
		}
		return false;
	}

  return true;
}

// ============================================================================
// KeithleySCPIProtocol::set_range
// ============================================================================
void KeithleySCPIProtocol::set_range (std::string value) 
{
std::string cmd_to_send("");
std::string tmpMode;

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_range()");
	}
	
	//- get electrometer mode
	tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command to Keithley device
	cmd_to_send = tmpMode + ":RANGe " + value ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::zero_check_on
// ============================================================================
void KeithleySCPIProtocol::zero_check_on (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_check_on()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCH ON" ;
	_communication_link->write(cmd_to_send);

}
// ============================================================================
// KeithleySCPIProtocol::zero_check_off
// ============================================================================
void KeithleySCPIProtocol::zero_check_off (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_check_off()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCH OFF";
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::zero_correct_on
// ============================================================================
void KeithleySCPIProtocol::zero_correct_on (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_correct_on()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCOR ON" ;
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::zero_correct_off
// ============================================================================
void KeithleySCPIProtocol::zero_correct_off (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_correct_off()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCOR OFF" ;
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::zero_correct_state_on
// ============================================================================
void KeithleySCPIProtocol::zero_correct_state_on (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_correct_state_on()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCOR:STAT ON" ;
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::zero_correct_state_off
// ============================================================================
void KeithleySCPIProtocol::zero_correct_state_off (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::zero_correct_state_off()");
	}
	
	//- send command
	cmd_to_send = "SYST:ZCOR:STAT OFF" ;
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::autoRange_ON
// ============================================================================
void KeithleySCPIProtocol::autoRange_on (void) 
{
std::string cmd_to_send("");
std::string tmpMode;
	
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::autoRange_ON()");
	}
	
	//- get electrometer mode
	tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );

	cmd_to_send = tmpMode + ":RANGe:AUTO ON" ;
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::autoRange_OFF
// ============================================================================
void KeithleySCPIProtocol::autoRange_off (void) 
{
std::string cmd_to_send("");
std::string tmpMode;
	
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::autoRange_off()");
	}
	
	//- get electrometer mode
	tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );

	//- send command
	cmd_to_send = tmpMode + ":RANGe:AUTO OFF";
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::auto_zero_on
// ============================================================================
void KeithleySCPIProtocol::auto_zero_on (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::auto_zero_on()");
	}
	
	//- send command
	cmd_to_send = "SYST:AZER ON" ;
	_communication_link->write(cmd_to_send);

}
// ============================================================================
// KeithleySCPIProtocol::auto_zero_off
// ============================================================================
void KeithleySCPIProtocol::auto_zero_off (void) 
{
std::string cmd_to_send("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::auto_zero_off()");
	}
	
	//- send command
	cmd_to_send = "SYST:AZER OFF" ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::MODE -> Ampere, Volt, Ohm, Coulomb and V on I meters
// ============================================================================
// ============================================================================
// KeithleySCPIProtocol::setAmperMeterMode
// ============================================================================
void KeithleySCPIProtocol::setAmperMeterMode (void) 
{
std::stringstream cmd_to_send;
std::string mode ("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setAmperMeterMode()");
	}
	
	//- mode current (send CURR)
	mode = "CURRent";

	//- send command
	cmd_to_send << "FUNC \'" << mode << "\'" << std::endl;
	_communication_link->write(cmd_to_send.str());

}

// ============================================================================
// KeithleySCPIProtocol::setVoltMeterMode
// ============================================================================
void KeithleySCPIProtocol::setVoltMeterMode (void) 
{
std::stringstream cmd_to_send;
std::string mode ("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setVoltMeterMode()");
	}
	
	//- mode volt
	mode = "VOLTage";

	//- send command
	cmd_to_send << "FUNC \'" << mode << "\'" << std::endl;
	_communication_link->write(cmd_to_send.str());
}

// ============================================================================
// KeithleySCPIProtocol::setOhmMeterMode
// ============================================================================
void KeithleySCPIProtocol::setOhmMeterMode (void) 
{
std::stringstream cmd_to_send;
std::string mode ("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setOhmMeterMode()");
	}
	
	//- mode ohm
	mode = "RESistance";

	//- send command
	cmd_to_send << "FUNC \'" << mode << "\'" << std::endl;
	_communication_link->write(cmd_to_send.str());

}

// ============================================================================
// KeithleySCPIProtocol::setCoulombMeterMode
// ============================================================================
void KeithleySCPIProtocol::setCoulombMeterMode (void) 
{
std::stringstream cmd_to_send;
std::string mode ("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setCoulombMeterMode()");
	}
	
	//- mode coulomb
	mode = "CHARge";

	//- send command
	cmd_to_send << "FUNC \'" << mode << "\'" << std::endl;
	_communication_link->write(cmd_to_send.str());

}

// ============================================================================
// KeithleySCPIProtocol::setVSourceOutputON
// ============================================================================
void KeithleySCPIProtocol::setVSourceOutputON (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setVSourceOutputON()");
	}
	
std::string cmd_to_send ("OUTP 1");

	//- send command
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::setVSourceOutputOFF
// ============================================================================
void KeithleySCPIProtocol::setVSourceOutputOFF (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setVSourceOutputOFF()");
	}
	
std::string cmd_to_send ("OUTP 1");
	//- send command
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::setVSourceValue
// ============================================================================
void KeithleySCPIProtocol::setVSourceValue (double voltsValue) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::setVSourceValue()");
	}
	
std::stringstream cmd_to_send;
	//- send command
  cmd_to_send << "SOUR:VOLT " << voltsValue << std::endl;
	_communication_link->write(cmd_to_send.str());
}

// ============================================================================
// KeithleySCPIProtocol::getVSourceValue
// ============================================================================
std::string KeithleySCPIProtocol::getVSourceValue (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::getVSourceValue()");
	}
	
std::string cmd_to_send("SOUR:VOLT?");
	//- send command
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_mode
// ============================================================================
std::string KeithleySCPIProtocol::get_mode (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_mode()");
	}
	
std::string cmd_to_send("");
	//- get electrometer mode
	if(isDiffSuportedMode)
	{
		//- send command
		cmd_to_send = "FUNC?" ;
		_mode =  _communication_link->write_read(cmd_to_send);
		//- _mode returned is as this "RES" so, erase " caracters
		_mode.erase(_mode.find("\""), 1);
		_mode.erase(_mode.find("\""), 1);
	}
	else
		_mode = "CURR\n";

	return _mode;
}

// ============================================================================
// KeithleySCPIProtocol::get_range
// ============================================================================
std::string KeithleySCPIProtocol::get_range (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_range()");
	}
	
std::string cmd_to_send("");
	//- get electrometer mode
	std::string tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command
	cmd_to_send = tmpMode + ":RANGe?" ;
	std::string _rangeStr = _communication_link->write_read(cmd_to_send);
	
	return _rangeStr;
}

// ============================================================================
// KeithleySCPIProtocol::get_value
// ============================================================================
std::string KeithleySCPIProtocol::get_value (void) 
{
std::string cmd_to_send("");
std::string tmp("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_value()");
	}
	
	////- This command performs a CONFIGURE and a READ?
	//cmd_to_send = "MEAS?" ;
	
	//- This command performs an INIT and then query the updated value
    cmd_to_send = "READ?" ;

	tmp = _communication_link->write_read(cmd_to_send);

  //- extract all data
  return tmp;
}

// ============================================================================
// KeithleySCPIProtocol::get_integratedValue
// ============================================================================
std::vector<double> KeithleySCPIProtocol::get_integratedValue (void) 
{
std::string cmd_to_send("");
std::string tmp("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_integratedValue()");
	}
	
	//- This command performs an INIT and then query the bufferised values
	cmd_to_send = "TRAC:DATA?" ;
	tmp = _communication_link->write_read(cmd_to_send);

  //- extract all data
  return buildDataList(tmp);
}

// ============================================================================
// KeithleySCPIProtocol::get_fetchValue
// ============================================================================
std::vector<double> KeithleySCPIProtocol::get_fetchValue (void) 
{
std::string cmd_to_send("");
std::string tmp("");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_fetchValue()");
	}
	
	//- This command queries the last value(s)
	cmd_to_send = "FETCh?" ;
	tmp = _communication_link->write_read(cmd_to_send);

  //- extract all data
  return buildDataList(tmp);

}

// ============================================================================
// KeithleySCPIProtocol::buildDataList
//
//  This method extract and convert data from the received string
// ============================================================================
std::vector<double> KeithleySCPIProtocol::buildDataList(std::string datalist)
{
std::string dataStr("");
std::vector<double> argout;
std::string::size_type posBeg;
std::string::size_type posEnd;
short numberOfData = 0;
	//- 
	posBeg = 0;
	posEnd = datalist.find(',', posBeg);

//-DEBUG 
std::cout << "\t*****::buildDataList -> argin :\n$" << datalist << "$" << std::endl;
  
	//- there is just one value
  if(posEnd == std::string::npos)
  {
		  argout.push_back( XString<double>::convertFromString(datalist) );
//-DEBUG 
std::cout << "\t*****::buildDataList -> JUST ONE DATA :$" << datalist << "$" << std::endl;
  }
  else
  {
	  int i = 0;
    //std::string tmp = get_triggercount();
    numberOfData =  XString<short>::convertFromString(get_triggercount());

    for(i=0; i < numberOfData; i++)
    {
		  dataStr = datalist.substr(posBeg,posEnd);
		  argout.push_back( XString<double>::convertFromString(dataStr) );
//-DEBUG 
std::cout << "\t*****::buildDataList -> FULL OF DATA : " << i << " -> $" << argout[i] << "$" << std::endl;
      posBeg = posEnd+1;
		  posEnd = datalist.find(',', posBeg);

      //- end of string reached so latest data is here
      if(posEnd == std::string::npos)
      {
        dataStr = datalist.substr(posBeg);
   		  argout.push_back( XString<double>::convertFromString(dataStr) );
        break;
      }
    }
  }

	return argout;
}

// ============================================================================
// KeithleySCPIProtocol::init_keithley to perform reading(s) data
// ============================================================================
void KeithleySCPIProtocol::init_keithley (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::init_keithley()");
	}

#ifdef WIN32
  Sleep( 10 ); //- sleep just a few
#else
  usleep(10000);
#endif

std::string cmd_to_send("INIT");
	//- send command : INIT to trigg readings !
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::abort -> cancel all operations started by INIT command
// ============================================================================
void KeithleySCPIProtocol::abort (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::abort()");
	}
	
std::string cmd_to_send("ABORt");
	//- send command : ABORt to cancel all operations
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_knplc : specify the integration rate
// ============================================================================
void KeithleySCPIProtocol::set_knplc (std::string nbNPLC) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_knplc()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
std::string cmd_to_send("");
	//- send command
	cmd_to_send = tmpMode + ":NPLC " + nbNPLC ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_knplc : get the integration rate
// ============================================================================
std::string KeithleySCPIProtocol::get_knplc (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_knplc()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase( tmpMode.find("\n") );
	
std::string cmd_to_send("");
	//- send command
	cmd_to_send = tmpMode + ":NPLCycles?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_triggercount
// ============================================================================
void KeithleySCPIProtocol::set_triggercount (std::string nbTrigCount) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_triggercount()");
	}
	
std::string cmd_to_send("");
	//- send command
	cmd_to_send = "TRIG:COUN " + nbTrigCount ;
	//- for internal use ( = keithley device buffer size)
	trigCountStr = nbTrigCount;

	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_triggercount
// ============================================================================
std::string KeithleySCPIProtocol::get_triggercount (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_triggercount()");
	}
	
	//- send command
	std::string cmd_to_send("TRIG:COUNt?");
	std::string response  = _communication_link->write_read(cmd_to_send);

  return response;
}

// ============================================================================
// KeithleySCPIProtocol::set_triggerdelay
// ============================================================================
void KeithleySCPIProtocol::set_triggerdelay (std::string trigDelay) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_triggerdelay()");
	}
	
	//- send command
	std::string cmd_to_send = "TRIG:DEL " + trigDelay ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_triggerdelay
// ============================================================================
std::string KeithleySCPIProtocol::get_triggerdelay (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_triggerdelay()");
	}
	
	//- send command
	std::string cmd_to_send = "TRIG:DEL?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_triggerdelayAuto
// ============================================================================
void KeithleySCPIProtocol::set_triggerdelayAuto (std::string trigDelayAuto) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_triggerdelayAuto()");
	}
	
	//- send command
	std::string cmd_to_send = "TRIG:DEL:" + trigDelayAuto ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_triggerdelayAuto
// ============================================================================
std::string KeithleySCPIProtocol::get_triggerdelayAuto (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_triggerdelayAuto()");
	}
	
	//- send command
	std::string cmd_to_send = "TRIG:DEL:AUTO?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_averagecount
// ============================================================================
void KeithleySCPIProtocol::set_averagecount (std::string nbAverageCount) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_averagecount()");
	}
	
	//- send command
	std::string cmd_to_send = "AVER:COUN " + nbAverageCount;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_averagecount
// ============================================================================
void KeithleySCPIProtocol::set_averagecount_K6517 (std::string cmd_to_send) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_averagecount()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase( tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER:COUN " + cmd_to_send ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_averagecount
// ============================================================================
std::string KeithleySCPIProtocol::get_averagecount (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_averagecount()");
	}
	
	//- send command
	std::string cmd_to_send("AVER:COUNt?");
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_averagecount
// ============================================================================
std::string KeithleySCPIProtocol::get_averagecount_K6517 (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_averagecount()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER:COUNt?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_averagecontrol
// ============================================================================
void KeithleySCPIProtocol::set_averagecontrol (std::string nbAverageControl) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_averagecontrol()");
	}
	
	//- send command
	std::string cmd_to_send = "AVER:TCON " + nbAverageControl;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::set_averagecontrol
// ============================================================================
void KeithleySCPIProtocol::set_averagecontrol_K6517 (std::string nbAverageControl) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_averagecontrol_K6517()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER:TCON " + nbAverageControl;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_averagecontrol
// ============================================================================
std::string KeithleySCPIProtocol::get_averagecontrol (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_averagecontrol()");
	}
	
	//- send command
	std::string cmd_to_send = "AVER:TCONtrol?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_averagecount
// ============================================================================
std::string KeithleySCPIProtocol::get_averagecontrol_K6517 (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_averagecontrol_K6517()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode( );

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER:TCONtrol?" ;
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::clear_registers
// ============================================================================
void KeithleySCPIProtocol::clear_registers (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::clear_registers()");
	}
	
	//- send command
	std::string cmd_to_send("*CLS");
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::averageStateON
// ============================================================================
void KeithleySCPIProtocol::averageStateON (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::averageStateON()");
	}
	
	//- send command
	std::string cmd_to_send = "AVER ON" ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::averageStateON_K6517
// ============================================================================
void KeithleySCPIProtocol::averageStateON_K6517 (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::averageStateON_K6517()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase( tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER ON";
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::averageStateOFF
// ============================================================================
void KeithleySCPIProtocol::averageStateOFF (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::averageStateOFF()");
	}
	
	//- send command
	std::string cmd_to_send = "AVER OFF";
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::averageStateOFF_K6517
// ============================================================================
void KeithleySCPIProtocol::averageStateOFF_K6517 (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::averageStateOFF_K6517()");
	}
	
	//- get electrometer mode
	std::string tmpMode = get_mode();

	//- erase bad caracters
	tmpMode.erase(tmpMode.find("\n") );
	
	//- send command
	std::string cmd_to_send = tmpMode + ":AVER OFF" ;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::reset
// ============================================================================
void KeithleySCPIProtocol::reset (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::reset()");
	}
	
	//- send command
	std::string cmd_to_send = "*RST" ;
	_communication_link->write(cmd_to_send);

  //- Select reading only
  cmd_to_send = "FORM:ELEM READ";

	//- send command
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_raw_status
// ============================================================================
std::string KeithleySCPIProtocol::get_raw_status (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_raw_status()");
	}
	
	//- send command : read error queue only
	std::string cmd_to_send = "STAT:QUE?";
	std::string argout = _communication_link->write_read(cmd_to_send);

	return argout;
}

// ============================================================================
// KeithleySCPIProtocol::set_buffer_size()
// ============================================================================
void KeithleySCPIProtocol::set_buffer_size (std::string size) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::set_buffer_size()");
	}
	
	//- send command : size = number of triggers
	std::string cmd_to_send = "TRAC:POIN " + size;
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::get_buffer_size()
// ============================================================================
std::string KeithleySCPIProtocol::get_buffer_size ( ) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::get_buffer_size()");
	}
	
	//- send command :
	std::string cmd_to_send("TRAC:POIN:ACTual?");
	return _communication_link->write_read(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::clear_buffer()
// ============================================================================
void KeithleySCPIProtocol::clear_buffer (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::clear_buffer()");
	}
	
	//- send command : clear previous data
	std::string cmd_to_send("TRAC:CLEAR");
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::store_raw_input()
// ============================================================================
void KeithleySCPIProtocol::store_raw_input (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::store_raw_input()");
	}
	
	std::string cmd_to_send("TRAC:FEED SENS");
	//- send command : Store raw input readings
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::start_storing()
// ============================================================================
void KeithleySCPIProtocol::start_storing (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::start_storing()");
	}
	
	std::string cmd_to_send("TRAC:FEED:CONT NEXT");
	//- send command : Start storing readings
	_communication_link->write(cmd_to_send);
}

// ============================================================================
// KeithleySCPIProtocol::save_configuration
// ============================================================================
void KeithleySCPIProtocol::save_configuration (unsigned short memoryIdx) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::save_configuration()");
	}
	
std::stringstream cmd_to_send;
	//- send command
  cmd_to_send << "*SAV " << memoryIdx << std::endl;
	_communication_link->write(cmd_to_send.str());
}

// ============================================================================
// KeithleySCPIProtocol::restore_configuration
// ============================================================================
void KeithleySCPIProtocol::restore_configuration (unsigned short memoryIdx) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::restore_configuration()");
	}
	
std::stringstream cmd_to_send;
	//- send command
  cmd_to_send << "*RCL " << memoryIdx << std::endl;
	_communication_link->write(cmd_to_send.str());
}

// ============================================================================
// KeithleySCPIProtocol::enable_SRQBufferFull()
// ============================================================================
void KeithleySCPIProtocol::enable_SRQBufferFull (void) 
{
/**********************************************************/
/*  NOTE :                                                */
/* 512 is the 10th bit in the MESUREMENT EVENT REGISTERS  */
/* which the BUFFER FULL bit that can be enabled          */
/**********************************************************/
  
  std::string cmd_to_send("STAT:MEAS:ENAB 512");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::enable_SRQBufferFull()");
	}
	
	//- send command : enable buffer full in the Measurement event enable register
	_communication_link->write(cmd_to_send);

  //- Program the service request enable register: to send SRQ on Buffer Full !
  cmd_to_send = "*SRE 1";

	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::disable_SRQBufferFull()
// ============================================================================
void KeithleySCPIProtocol::disable_SRQBufferFull (void) 
{
std::string cmd_to_send("STAT:MEAS?");

	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::disable_SRQBufferFull()");
	}
	
	//- send command : disable buffer full event
	_communication_link->write_read(cmd_to_send);

  //- Disable the service request enable register
  cmd_to_send = "*SRE 0";
	_communication_link->write(cmd_to_send);

}

// ============================================================================
// KeithleySCPIProtocol::SRQLineState()
// ============================================================================
bool KeithleySCPIProtocol::SRQLineState (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::SRQLineState()");
	}
	
	//- if asserted -> the programmed event occurs : the device can be asked !
	return _communication_link->SRQLineState();

  //- Cf Keithley doc to know how the to get the wanted event 
  //-   Chapter : Status Structure
}

// ============================================================================
// KeithleySCPIProtocol::readStatusByteRegister()
// ============================================================================
short KeithleySCPIProtocol::readStatusByteRegister (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::readStatusByteRegister()");
	}
	
	//- if SRQ line UP -> the programmed event(s) occurs : the value is available !
	return _communication_link->readStatusByteRegister();

  //- Cf Keithley doc to know how the to get the wanted event 
  //-   Chapter : Status Structure
}

// ============================================================================
// KeithleySCPIProtocol::read_data_with_no_timestamp
// ============================================================================
void KeithleySCPIProtocol::read_data_with_no_timestamp (void) 
{
	if( !this->_communication_link )
	{
		throw electrometer::ElectrometerException(
												"INITIALIZATION_ERROR", 
												"No communication protocol available.",
												"KeithleySCPIProtocol::read_data_with_no_timestamp()");
	}
	
	std::string cmd_to_send("FORM:ELEM READ");
	_communication_link->write(cmd_to_send);
}





// Following functions are part of commands supported via the SCPI protocol. 
// We may have to implement them after first tests on beamlines

/*
// ============================================================================
// KeithleySCPIProtocol::setExternalFeedbackMeterMode
// ============================================================================
void KeithleySCPIProtocol::setExternalFeedbackMeterMode (void) 
{
std::stringstream cmd_to_send;

		cmd_to_send << "F4X" << std::endl;
		_communication_link->write(cmd_to_send());

}

// ============================================================================
// KeithleySCPIProtocol::setVonIMeterMode
// ============================================================================
void KeithleySCPIProtocol::setVonIMeterMode (void) 
{
std::stringstream cmd_to_send;

	//- send command
	try
	{
		cmd_to_send << "F5X" << std::endl;
		_communication_link->write(cmd_to_send.str());
	}
	catch(Tango::DevFailed& df)
	{
		Tango::Except::re_throw_exception (df,
										(const char*)"COMMUNICATION_ERROR",
										(const char*)"Unable to perform a write operation",
										(const char*)"KeithleySCPIProtocol::setVonIMeterMode");
	}
	catch(...)
	{
		throw ;
	}

}
*/

/* TO BE IMPLEMENTED !!!!! 

// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::reading_source (void) 
{

}

// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::data_store (void) 
{

}

// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::data_format (void) 
{

}

// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::baseline_suppression_ON (void) 
{

}

// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::baseline_suppression_OFF (void) 
{

}
// ============================================================================
// KeithleySCPIProtocol::reading_source
// ============================================================================
void KeithleySCPIProtocol::keithley_status (void) 
{

}
*/