Skip to content
Snippets Groups Projects
  • ELATTAOUI's avatar
    af62225b
    xavier : for DDC part · af62225b
    ELATTAOUI authored
    - integration mode OK (tests done with K_486)
    
    - TODO: DDC/SCPI
    integration time for ScanServer compatibility.
    report config for all DDC
    add configuration in SCPI start command
    af62225b
    History
    xavier : for DDC part
    ELATTAOUI authored
    - integration mode OK (tests done with K_486)
    
    - TODO: DDC/SCPI
    integration time for ScanServer compatibility.
    report config for all DDC
    add configuration in SCPI start command
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Keithley_487.cpp 14.90 KiB
// ============================================================================
//
// = CONTEXT
//    TANGO Project - DDC KeithleyElectrometer Support Library
//
// = FILENAME
//    Keithley_487.cpp
//
// = AUTHOR
//    X. Elattaoui
//
// ============================================================================
static long KEITHLEY_MODEL = 487;

// ============================================================================
// DEPENDENCIES
// ============================================================================
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <Xstring.h>
#include "Keithley_487.h"
#include "KeithleyDDCProtocol.h"
/*
* Valid Range values for a K_487
*/
static const std::string K487_rangeValue[] = {"AUTO ON","2E-9","2E-8","2E-7","2E-6","2E-5","2E-4","2E-3", "AUTO OFF"};
/*
* Range limit : no range for values R8 & R9 (R10 = AUTORANGE OFF)
*/
static short K487_rangeLimit = 8;

/*
* Trigger Mode limit
*/
static short K487_triggerModeLimit = 9;


// ============================================================================
// Keithley_487::Keithley_487
// ============================================================================
Keithley_487::Keithley_487 (std::string& comLink_device_name):AbstractElectrometerClass(comLink_device_name) 
{
	std::cout << "Keithley_487::Keithley_487 <-" << std::endl;

	//- build the keithley Electrometer obj
	_electrometerProtocol = new KeithleyDDCProtocol (_device_proxy_name);

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

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

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

// ============================================================================
// Keithley_487::autoRange_off
// ============================================================================
void Keithley_487::autoRange_off (void) 
{

	//- send the appropriate command
	KeithleyDDCProtocol* _kddc = dynamic_cast<KeithleyDDCProtocol*>(_electrometerProtocol);
	if(_kddc)
		_kddc->autoRange_OFF_forK486_487();
}

// ============================================================================
// Keithley_487::range_up
// ============================================================================
void Keithley_487::range_up (void) 
{
std::stringstream cmd_to_send;

	// force read of range on instrument to update _range variable 
	electrometer_status();

	_range += 1;

	if(_range > K487_rangeLimit)
	{
		_range = K487_rangeLimit;

		throw electrometer::ElectrometerException("OUT_OF_RANGE", 
												"Range up limit reached.",
												"Keithley_487::range_up( ).");
	}

	//- build and send the command
	cmd_to_send << _range << std::endl;
	_electrometerProtocol->set_range(cmd_to_send.str());
}

// ============================================================================
// Keithley_487::range_down
// ============================================================================
void Keithley_487::range_down (void) 
{
std::stringstream cmd_to_send;

	// force read of range on instrument to update _range variable 
	electrometer_status();

	_range -= 1;

	if(_range < 0)
	{
		_range=0;

		throw electrometer::ElectrometerException("OUT_OF_RANGE", 
												"Range down limit reached.",
												"Keithley_487::range_down( ).");
	}
	//- build and send the command
	cmd_to_send << _range << std::endl;
	_electrometerProtocol->set_range(cmd_to_send.str());
}

// ============================================================================
// Keithley_487::get_ElectroMeterRange
// ============================================================================
std::string Keithley_487::get_ElectroMeterRange (void) 
{
	// force read of range on instrument to update _range variable
	electrometer_status();

	return _rangeStr;
}

// ============================================================================
// Keithley_487::set_buffer_size()
// ============================================================================
void Keithley_487::set_buffer_size (short size) 
{
std::stringstream cmd_to_send;

  //- check if size is valid
  if(size<0 || size>512)
		throw electrometer::ElectrometerException("OUT_OF_RANGE", 
												"Buffer size value invalid. Please enter a value in the range 0 - 512.",
												"Keithley_487::set_buffer_size( ).");

	//- send command : size = number of triggers
  cmd_to_send << "N" << size << "X" << std::endl;
	_electrometerProtocol->set_buffer_size(cmd_to_send.str());

}

// ============================================================================
// Keithley_487::set_triggerMode
// ============================================================================
void Keithley_487::set_triggerMode (short trigMod) 
{
  if(trigMod<0 || trigMod>K487_triggerModeLimit)
		throw electrometer::ElectrometerException("OUT_OF_RANGE", 
												"Trigger mode value invalid. Please enter a value in the range 0 - 7.",
												"Keithley_487::set_triggerMode( ).");

  std::stringstream cmd_to_send;

  cmd_to_send << trigMod <<  std::endl;

  _electrometerProtocol->set_triggerMode(cmd_to_send.str());

}

// ============================================================================
// Keithley_487::get_ElectroMeterMode
// ============================================================================
std::string Keithley_487::get_ElectroMeterMode (void) 
{
	// force read of range on instrument to update _range variable
	electrometer_status();

	return _mode;
}

// ============================================================================
// Keithley_487::setAmperMeterMode
// ============================================================================
void Keithley_487::setAmperMeterMode (void) 
{

	//- send the appropriate command
	KeithleyDDCProtocol* _kddc = dynamic_cast<KeithleyDDCProtocol*>(_electrometerProtocol);
	if(_kddc)
		_kddc->setAmperMeterMode_forK487();
	else
		throw electrometer::ElectrometerException("BAD_CAST", 
												"Unable to switch the electrmometer mode.",
												"Keithley_487::setAmperMeterMode( ).");
}

// ============================================================================
// Keithley_487::init_keithley : command to perform an integration cycle
// ============================================================================
void Keithley_487::init_keithley (void) 
{
  //- default conversion rate
  _electrometerProtocol->set_conversionRate( );
  //- set default integration period
  _electrometerProtocol->enable_integrationPeriod( );
  //- enable readings from device buffer
  _electrometerProtocol->enable_readingsFromBuffer_K486_487( );
  //- force readings with no prefix
  _electrometerProtocol->disable_readingWithPrefix();
  //- enable SRQ on buffer full
  _electrometerProtocol->enable_SRQBufferFull ();
}

// ============================================================================
// Keithley_487::electrometer_status
// ============================================================================
std::string Keithley_487::electrometer_status (void)
{ 
	std::string _kstatus("undefined status");
	std::string argout("undefined status");
	std::string tmp("");

	//- read keithley status from HW	
	_kstatus = _electrometerProtocol->get_raw_status();

	//- build status
	try
	{
		std::string modelNum = _kstatus.substr(0,3);
		//- if not expected data (here model number)
		if(modelNum.find("487") == std::string::npos)
		{
			set_electroState(ALARM);
			argout = "Invalid status string received";
			return argout;
		}
		argout = "Keithley Type : " + modelNum + "\n";
		//- Display Intensity ('A')
		tmp = _kstatus.substr(_kstatus.find('A')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Display Intensity : NORMAL\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Display Intensity : DIM\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Display Intensity : OFF\n";
		//- Reading Source ('B')
		tmp = _kstatus.substr(_kstatus.find('B'),1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Reading Source : A/D Reading\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Reading Source : One Data Store Reading\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Reading Source : All Data Store Reading\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "Reading Source : Max Data Store Reading\n";
		else
		if(XString<short>::convertFromString(tmp) == 4)
			argout += "Reading Source : Min Data Store Reading\n";
		//- Zero check state ('C')
		tmp = _kstatus.substr(_kstatus.find('C')+1,1);
		if(XString<short>::convertFromString(tmp))
			argout += "Zero Check : Enabled\n";
		else
			argout += "Zero Check : Disabled\n";
		//- V/I Ohms ('F')
		tmp = _kstatus.substr(_kstatus.find('F')+1,1);
		if(XString<short>::convertFromString(tmp))
		{
			argout += "V/I Ohms : Enabled\n";
			_mode = "V/I Ohms";
		}
		else
		{
			argout += "V/I Ohms : Disabled\n";
			_mode = "CURRent";
		}
		//- Data Format ('G')
		tmp = _kstatus.substr(_kstatus.find('G')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Data Format : Reading With Prefix (ASCII)\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Data Format : Reading Without Prefix (ASCII)\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Data Format : Reading and Buffer Location With Prefix (ASCII)\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "Data Format : Reading and Buffer Location Without Prefix (ASCII)\n";
		else
		if(XString<short>::convertFromString(tmp) == 4)
			argout += "Data Format : Binary Reading - precision, bytes reversed for Intel CPUs\n";
		else
		if(XString<short>::convertFromString(tmp) == 5)
			argout += "Data Format : Binary Reading - precision, bytes in normal order for Motorola CPUs\n";
		else
		if(XString<short>::convertFromString(tmp) == 6)
			argout += "Data Format : Binary Reading - counts and exponent, bytes reversed for Intel CPUs\n";
		else
		if(XString<short>::convertFromString(tmp) == 7)
			argout += "Data Format : Binary Reading - counts and exponent, bytes in normal order for Motorola CPUs\n";
		//- Self Test ('J')
		tmp = _kstatus.substr(_kstatus.find('J')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Self Test : No Errors\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Self Test : ROM Error\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Self Test : RAM Error\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "Self Test : ROM and RAM Error\n";
		//- EOI & Bus Hold Off ('K')
		tmp = _kstatus.substr(_kstatus.find('K')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "EOI & Bus Hold Off : EOI and Hold-Off\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "EOI & Bus Hold Off : No EOI and Hold-Off\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "EOI & Bus Hold Off : EOI and no Hold-Off\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "EOI & Bus Hold Off : No EOI and no Hold-Off\n";
		//- SRQ ('M')
		tmp = _kstatus.substr(_kstatus.find('M')+1,3);
		if(!XString<short>::convertFromString(tmp))
			argout += "SRQ : Disabled\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "SRQ : Reading Overflow\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "SRQ : Data Store Full\n";
		else
		if(XString<short>::convertFromString(tmp) == 4)
			argout += "SRQ : Data Store 1/2 full\n";
		else
		if(XString<short>::convertFromString(tmp) == 8)
			argout += "SRQ : Reading Done\n";
		else
		if(XString<short>::convertFromString(tmp) == 16)
			argout += "SRQ : Ready\n";
		else
		if(XString<short>::convertFromString(tmp) == 32)
			argout += "SRQ : Error\n";
		else
		if(XString<short>::convertFromString(tmp) == 128)
			argout += "SRQ : Voltage Source Error\n";
		//- Data Store Size ('N')
		tmp = _kstatus.substr(_kstatus.find('N')+1,3);
		if(!XString<short>::convertFromString(tmp))
			argout += "Data Store Size : Wrap Around\n";
		else
			argout += "Data Store Size : " + tmp + "\n";
		//- Filters ('P')
		tmp = _kstatus.substr(_kstatus.find('P')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Filters : Both Filters Disabled\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Filters : Digital Filter Enabled, Analog Filter Disabled\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Filters : Digital Filter Disabled, Analog Filter Enabled\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "Filters : Both Filters Enabled\n";
		//- Range ('Rmn')
		//- check AutoRange
		tmp = _kstatus.substr(_kstatus.find('R')+1,2);
		if(tmp[0] == '0')
			argout += "Range : AutoRange Disabled\n";
		else
			argout += "Range : AutoRange Enabled\n";
		//- range value
		_range = atoi(&tmp[1]);
		_rangeStr = K487_rangeValue[_range];
		argout   += _rangeStr + "\n";
		//- Integration Period ('S')
		tmp = _kstatus.substr(_kstatus.find('S')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Integration Period : Fast (4-1/2d)\n";
		else
			argout += "Integration Period : Line Cycle (5-1/2d)\n";
		//- Trigger ('T')
		tmp = _kstatus.substr(_kstatus.find('T')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Trigger : Multiple On Talk\n";
		else
		if(XString<short>::convertFromString(tmp) == 1)
			argout += "Trigger : One-shot On Talk\n";
		else
		if(XString<short>::convertFromString(tmp) == 2)
			argout += "Trigger : Multiple On Get\n";
		else
		if(XString<short>::convertFromString(tmp) == 3)
			argout += "Trigger : One-shot On Get)\n";
		else
		if(XString<short>::convertFromString(tmp) == 4)
			argout += "Trigger : Multiple On X\n";
		else
		if(XString<short>::convertFromString(tmp) == 5)
			argout += "Trigger : One-shot On X\n";
		else
		if(XString<short>::convertFromString(tmp) == 6)
			argout += "Trigger : Multiple On External Trigger\n";
		else
		if(XString<short>::convertFromString(tmp) == 7)
			argout += "Trigger : One-shot On External Trigger\n";
		else
		if(XString<short>::convertFromString(tmp) == 8)
			argout += "Trigger : Multiple On Operate\n";
		else
		if(XString<short>::convertFromString(tmp) == 9)
			argout += "Trigger : One-shot On Operate\n";
		//- Relative ('Z') (baseline suppress)
		tmp = _kstatus.substr(_kstatus.find('Z')+1,1);
		if(!XString<short>::convertFromString(tmp))
			argout += "Relative : Current Rel Disabled\n";
		else
			argout += "Relative : Current Rel Enabled\n";
	}
	catch(std::out_of_range)
	{
		set_electroState(ALARM);

		throw electrometer::ElectrometerException("OUT_OF_RANGE", 
												"Cannot extract device status [find or substr failed !].",
												"Keithley_487::electrometer_status( ).");
	}

	set_electroState(ON);
	return argout;
}