-
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_486.cpp 14.16 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 <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;
// ============================================================================
// 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;
//- 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_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);
//- 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;
}