Code owners
Assign users and groups as approvers for specific file changes. Learn more.
Keithley_486.cpp 14.98 KiB
// ============================================================================
//
// = CONTEXT
// TANGO Project - DDC KeithleyElectrometer Support Library
//
// = FILENAME
// Keithley_486.cpp
//
// = AUTHOR
// X. Elattaoui
//
// ============================================================================
static long KEITHLEY_MODEL = 486;
// ============================================================================
// DEPENDENCIES
// ============================================================================
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <math.h> //- for ceil
#include <Xstring.h>
#include "Keithley_486.h"
#include "KeithleyDDCProtocol.h"
/*
* Valid Range values for a K_486
*/
static const std::string K486_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 K486_rangeLimit = 8;
/*
* Trigger Mode limit
*/
static short K486_triggerModeLimit = 7;
/*
* Trigger Mode limit (millisec)
*/
static int K486_conversionRate = 360;
// ============================================================================
// Keithley_486::Keithley_486
// ============================================================================
Keithley_486::Keithley_486 (std::string& comLink_device_name):AbstractElectrometerClass(comLink_device_name)
{
std::cout << "Keithley_486::Keithley_486 <-" << std::endl;
//- build the keithley Electrometer obj
_electrometerProtocol = new KeithleyDDCProtocol(_device_proxy_name);
_size = -1;
_trigMod = -1;
std::cout << "Keithley_486::Keithley_486 ->" << std::endl;
}
// ============================================================================
// Keithley_486::~Keithley_486
// ============================================================================
Keithley_486::~Keithley_486 (void)
{
std::cout << "Keithley_486::~Keithley_486 <-" << std::endl;
std::cout << "Keithley_486::~Keithley_486 ->" << std::endl;
}
// ============================================================================
// Keithley_486::autoRange_off
// ============================================================================
void Keithley_486::autoRange_off (void)
{
//- send the appropriate command
KeithleyDDCProtocol* _kddc = dynamic_cast<KeithleyDDCProtocol*>(_electrometerProtocol);
if(_kddc)
_kddc->autoRange_OFF_forK486_487();
}
// ============================================================================
// Keithley_486::range_up
// ============================================================================
void Keithley_486::range_up (void)
{
std::stringstream cmd_to_send;
// force read of range on instrument to update _range variable
electrometer_status();
_range += 1;
if(_range > K486_rangeLimit)
{
_range =K486_rangeLimit;
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Range up limit reached.",
"Keithley_486::range_up( ).");
}
//- build and send the command
cmd_to_send << _range << std::endl;
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_486::range_down
// ============================================================================
void Keithley_486::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_486::range_down( ).");
}
//- build and send the command
cmd_to_send << _range << std::endl;
_electrometerProtocol->set_range(cmd_to_send.str());
}
// ============================================================================
// Keithley_486::get_ElectroMeterRange
// ============================================================================
std::string Keithley_486::get_ElectroMeterRange (void)
{
// force read of range on instrument to update _range variable
electrometer_status();
return _rangeStr;
}
// ============================================================================
// Keithley_486::set_buffer_size()
// ============================================================================
void Keithley_486::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( ).");
//- just for internal use
_size = 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_486::set_triggerMode (short trigMod)
{
if(trigMod<0 || trigMod>K486_triggerModeLimit)
throw electrometer::ElectrometerException("OUT_OF_RANGE",
"Trigger mode value invalid. Please enter a value in the range 0 - 7.",
"Keithley_486::set_triggerMode( ).");
std::stringstream cmd_to_send;
//- just for internal use
_trigMod = trigMod;
cmd_to_send << "T" << trigMod << "X" << std::endl;
_electrometerProtocol->set_triggerMode(cmd_to_send.str());
}
// ============================================================================
// Keithley_487::set_integrationTime
// ============================================================================
void Keithley_486::set_integrationTime (double seconds)
{
double msSeconds = seconds / 1000;
//- _size set in init_keithley()
_size = (int)ceil(msSeconds / K486_conversionRate);
}
// ============================================================================
// Keithley_486::init_keithley : command to perform an integration cycle
// ============================================================================
void Keithley_486::init_keithley (void)
{
//- default conversion rate
// _electrometerProtocol->set_conversionRate( );
//- set default integration period
// _electrometerProtocol->enable_integrationPeriod( );
//- set trigger mode
this->set_triggerMode(_trigMod);
//- default conversion rate
_electrometerProtocol->set_conversionRate( );
//- set buffer size
this->set_buffer_size(_size);
//- 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_486::electrometer_status
// ============================================================================
std::string Keithley_486::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
{
//- model number :
std::string modelNum = _kstatus.substr(0,3);
//- if not expected data (here model number)
if(modelNum.find("486") == 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);
// std::cout << "\nDisplay Intensity = *" << tmp <<"*" << std::endl;
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,1);
// std::cout << "\nReading Source = *" << tmp <<"*" << std::endl;
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);
// std::cout << "\nZero check state = *" << tmp <<"*" << std::endl;
if(XString<short>::convertFromString(tmp))
argout += "Zero Check : Enabled\n";
else
argout += "Zero Check : Disabled\n";
//- 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('J')+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);
// std::cout << "\ncheck AutoRange = *" << tmp[0] << "*" << std::endl;
// if(atoi(&tmp[0]) == 0)
if(tmp[0] == '0')
argout += "Range : AutoRange Disabled\n";
else
argout += "Range : AutoRange Enabled\n";
//- range value
// tmp = _kstatus.substr(_kstatus.find('R')+2,1);
_range = atoi(&tmp[1]);
_rangeStr = K486_rangeValue[_range];
// std::cout << "\nRange = *" << _range <<"*" << ", RangeStr=" << _rangeStr << std::endl;
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_486::electrometer_status( ).");
}
set_electroState(ON);
return argout;
}