-
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
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;
}