// ============================================================================ // // = CONTEXT // TANGO Project - DDC KeithleyElectrometer Support Library // // = FILENAME // Keithley_617.cpp // // = AUTHOR // X. Elattaoui // // ============================================================================ static long KEITHLEY_MODEL = 617; // ============================================================================ // DEPENDENCIES // ============================================================================ #include <iostream> #include <stdexcept> #include <sstream> #include <string> #include <Xstring.h> #include "Keithley_617.h" #include "KeithleyDDCProtocol.h" /* * Valid Range values for a K_617 */ static const std::string K617_AmpRangeValue[] = {"AUTO ON","2E-12","2E-11","2E-10","2E-9","2E-8","2E-7","2E-6","2E-5","2E-4","2E-3","2E-2", "AUTO OFF"}; static const std::string K617_VoltRangeValue[]= {"AUTO ON","2E-1","2","20","200","200","200","200","200","200","200","200", "AUTO OFF"}; static const std::string K617_OhmRangeValue[] = {"AUTO ON","2E3","2E4","2E5","2E6","2E7","2E8","2E9","2E10","2E11","2E11","2E11", "AUTO OFF"}; static const std::string K617_CouRangeValue[] = {"AUTO ON","2E-10","2E-9","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10","2E-10", "AUTO OFF"}; static const std::string K617_XfdbRangeValue[]= {"AUTO ON","2E-1","2","20","20","20","20","20","20","20","20","20", "AUTO OFF"}; static const std::string K617_VonIRangeValue[]= {"AUTO ON","200E12","20E12","2E12","200E9","20E9","2E9","200E6","20E6","2E6","200E3","200E3", "AUTO OFF"}; /* * Range limit */ static short K617_rangeLimit = 12; /* * Trigger Mode limit */ static short K617_triggerModeLimit = 7; // ============================================================================ // Keithley_617::Keithley_617 // ============================================================================ Keithley_617::Keithley_617 (std::string& comLink_device_name):AbstractElectrometerClass(comLink_device_name) { std::cout << "Keithley_617::Keithley_617 <-" << std::endl; //- build the keithley Electrometer obj _electrometerProtocol = new KeithleyDDCProtocol (_device_proxy_name); std::cout << "Keithley_617::Keithley_617 ->" << std::endl; } // ============================================================================ // Keithley_617::~Keithley_617 // ============================================================================ Keithley_617::~Keithley_617 (void) { std::cout << "Keithley_617::~Keithley_617 <-" << std::endl; std::cout << "Keithley_617::~Keithley_617 ->" << std::endl; } // ============================================================================ // Keithley_617::autoRange_off // ============================================================================ void Keithley_617::autoRange_off (void) { //- send the appropriate command KeithleyDDCProtocol* _kddc = dynamic_cast<KeithleyDDCProtocol*>(_electrometerProtocol); if(_kddc) _kddc->autoRange_OFF_forK617_6512(); } // ============================================================================ // Keithley_617::range_up // ============================================================================ void Keithley_617::range_up (void) { std::stringstream cmd_to_send; // force read of range on instrument to update _range variable _range += 1; if(_range > K617_rangeLimit) { _range = K617_rangeLimit; throw electrometer::ElectrometerException("OUT_OF_RANGE", "Range up limit reached.", "Keithley_617::range_up( )."); } //- build and send the command cmd_to_send << _range << std::endl; _electrometerProtocol->set_range(cmd_to_send.str()); } // ============================================================================ // Keithley_617::range_down // ============================================================================ void Keithley_617::range_down (void) { std::stringstream cmd_to_send; // force read of range on instrument to update _range variable _range -= 1; if(_range < 0) { _range = 0; throw electrometer::ElectrometerException("OUT_OF_RANGE", "Range down limit reached.", "Keithley_617::range_down( )."); } //- build and send the command cmd_to_send << _range << std::endl; _electrometerProtocol->set_range(cmd_to_send.str()); } // ============================================================================ // Keithley_617::get_ElectroMeterRange // ============================================================================ std::string Keithley_617::get_ElectroMeterRange (void) { // force read of range on instrument to update _range variable return _rangeStr; } // ============================================================================ // Keithley_617::set_buffer_size() // ============================================================================ void Keithley_617::set_buffer_size (short cmd) { throw electrometer::ElectrometerException("COMMAND_NOT_SUPPORTED", "The 617 Keithley device buffer size cannot be set (it stores up to 100 points internally.)", "Keithley_617::set_triggerMode( )."); } // ============================================================================ // Keithley_617::set_triggerMode // ============================================================================ void Keithley_617::set_triggerMode (short trigMod) { if(trigMod<0 || trigMod>K617_triggerModeLimit) throw electrometer::ElectrometerException("OUT_OF_RANGE", "Trigger mode value invalid. Please enter a value in the range 0 - 7.", "Keithley_617::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_617::get_ElectroMeterMode // ============================================================================ std::string Keithley_617::get_ElectroMeterMode (void) { // force read of mode on instrument to update _mode variable return _mode; } // ============================================================================ // Keithley_617::setAmperMeterMode (617 & 6512 Keithley DDC models // ============================================================================ void Keithley_617::setAmperMeterMode (void) { _electrometerProtocol->setAmperMeterMode( ); } // ============================================================================ // Keithley_617::setAmperMeterMode (617 & 6512 Keithley DDC models // ============================================================================ void Keithley_617::setVoltMeterMode (void) { _electrometerProtocol->setVoltMeterMode( ); } // ============================================================================ // Keithley_617::setAmperMeterMode (617 & 6512 Keithley DDC models // ============================================================================ void Keithley_617::setOhmMeterMode (void) { _electrometerProtocol->setOhmMeterMode( ); } // ============================================================================ // Keithley_617::setAmperMeterMode (617 & 6512 Keithley DDC models // ============================================================================ void Keithley_617::setCoulombMeterMode (void) { _electrometerProtocol->setCoulombMeterMode( ); } // ============================================================================ // Keithley_617::init_keithley : command to perform an integration cycle // ============================================================================ void Keithley_617::init_keithley (void) { //- set trigger mode this->set_triggerMode(_trigMod); //- default conversion rate _electrometerProtocol->set_conversionRate( ); //- force readings with no prefix _electrometerProtocol->disable_readingWithPrefix(); //- force readings from device buffer _electrometerProtocol->enable_readingsFromBuffer_K617_6512(); //- enable SRQ on buffer full _electrometerProtocol->enable_SRQBufferFull (); } // ============================================================================ // Keithley_617::electrometer_status // ============================================================================ std::string Keithley_617::electrometer_status (void) { std::string kconfig("undefined configuration"); std::string argout(""); std::string tmp(""); try { kconfig = _electrometerProtocol->get_raw_status(); std::string modelNum = kconfig.substr(0,3); if(modelNum.find("617") == std::string::npos) { set_electroState(ALARM); argout = "Invalid error status string received"; return argout; } //- IDDC Error : Set when an illegal device dependent command (IDDC) such as HlX is received ("H" is illegal). tmp = kconfig.substr(3,1); short iddc = XString<short>::convertFromString(tmp); if(iddc) { argout += "IDDC error : illegal device dependent command received.\n"; } //- IDDCO Error : Set when an illegal device-dependent command option (IDDCO) such as T9X is received ("9" is illegal). tmp = kconfig.substr(4,1); short iddco = XString<short>::convertFromString(tmp); if(iddco) { argout += "IDDCO error : an illegal device-dependent command option received.\n"; } //- Remote Error : Set when a programming command is received when REN is false. tmp = kconfig.substr(5,1); short remote = XString<short>::convertFromString(tmp); if(remote) { argout += "REMOTE error : programming command is received when REN is false\n"; } //- Trigger Overrun Error : Set when a trigger is received when the instrument is still processing a reading from a previous trigger. tmp = kconfig.substr(7,1); short trigg = XString<short>::convertFromString(tmp); if(trigg) { argout += "Trigger error : Trigger received while instrument is still processing a reading from a previous trigger.\n"; } //- Number Error : Set when an Out of range calibration or voltage source value is received. tmp = kconfig.substr(8,1); short numErr = XString<short>::convertFromString(tmp); if(numErr) { argout += "Number error : Out of range calibration or voltage source value is received.\n"; } if( argout.empty() ) argout = "No error."; argout = "Keithley Type " + modelNum + " Error Status :\n" + argout; } catch(...) { set_electroState(ALARM); throw electrometer::ElectrometerException("UNKNOWN_ERROR", "Cannot extract device error status.", "Keithley_617::electrometer_status( )."); } set_electroState(ON); return argout; } // ============================================================================ // Keithley_617::get_configuration // ============================================================================ std::string Keithley_617::get_configuration (void) { std::string _kstatus("undefined status"); std::string argout("undefined status"); std::string tmp(""); //- read keithley status from HW _kstatus = _electrometerProtocol->get_DDC_configuration(); //- build status try { //- model number : std::string modelNum = _kstatus.substr(0,3); // std::cout<< "\n617 status = " << modelNum << std::endl; //- if not expected data (here model number) if(modelNum.find("617") == std::string::npos) { set_electroState(ALARM); argout = "Invalid status string received"; return argout; } argout = "Keithley Type : " + modelNum + "\n"; //- Functions and associate range : tmp = _kstatus.substr(3,1); short func = XString<short>::convertFromString(tmp); //- Range : tmp = _kstatus.substr(4,2); _range = XString<short>::convertFromString(tmp); if(!func) { _mode = "Function : VOLTS"; argout += _mode + "\n"; _rangeStr = K617_VoltRangeValue[_range]; } else if(func == 1) { _mode = "Function : AMPS"; argout += _mode + "\n"; _rangeStr = K617_AmpRangeValue[_range]; argout += _rangeStr + "\n"; } else if(func == 2) { _mode = "Function : OHMS"; argout += _mode + "\n"; _rangeStr = K617_OhmRangeValue[_range]; } else if(func == 3) { _mode = "Function : COULOMBS"; argout += _mode + "\n"; _rangeStr = K617_CouRangeValue[_range]; } else if(func == 4) { _mode = "Function : XFDBK"; argout += _mode + "\n"; _rangeStr = K617_XfdbRangeValue[_range]; } else if(func == 5) { _mode = "Function : V/I"; argout += _mode + "\n"; _rangeStr = K617_XfdbRangeValue[_range]; } //- Range : argout += "RANGE : " + _rangeStr + "\n"; //- Zero check state tmp = _kstatus.substr(6,1); if(XString<short>::convertFromString(tmp)) argout += "Zero Check : ON\n"; else argout += "Zero Check : OFF\n"; //- Zero correct state tmp = _kstatus.substr(7,1); if(XString<short>::convertFromString(tmp)) argout += "Zero Correct : ON\n"; else argout += "Zero Correct : OFF\n"; //- Suppress tmp = _kstatus.substr(8,1); if(XString<short>::convertFromString(tmp)) argout += "Suppress : ON\n"; else argout += "Suppress : OFF\n"; //- Trigger tmp = _kstatus.substr(9,1); _trigMod = XString<short>::convertFromString(tmp); if(!_trigMod) argout += "Trigger : Continuous on Talk\n"; else if(_trigMod == 1) argout += "Trigger :One-Shot on Talk\n"; else if(_trigMod == 2) argout += "Trigger :Continuous on Get\n"; else if(_trigMod == 3) argout += "Trigger :One-Shot on Get\n"; else if(_trigMod == 4) argout += "Trigger :Continuous on \"X\"\n"; else if(_trigMod == 5) argout += "Trigger :One-Shot on \"X\"\n"; else if(_trigMod == 6) argout += "Trigger :Continuous on External\n"; else if(_trigMod == 7) argout += "Trigger :One-Shot on External\n"; //- Voltage Source tmp = _kstatus.substr(10,1); if(XString<short>::convertFromString(tmp)) argout += "Voltage Source Operate : ON\n"; else argout += "Voltage Source Operate : OFF\n"; //- Read Mode tmp = _kstatus.substr(11,1); if(!XString<short>::convertFromString(tmp)) argout += "Read Mode : Electrometer\n"; else if(XString<short>::convertFromString(tmp) == 1) argout += "Read Mode : Data Store\n"; else if(XString<short>::convertFromString(tmp) == 2) argout += "Read Mode : Maximum\n"; else if(XString<short>::convertFromString(tmp) == 3) argout += "Read Mode : Minimum\n"; else if(XString<short>::convertFromString(tmp) == 4) argout += "Read Mode :Voltage Source\n"; //- Display : tmp = _kstatus.substr(13,1); if(!XString<short>::convertFromString(tmp)) argout += "Display : Electrometer\n"; else argout += "Display : Voltage Source\n"; //- Data Store tmp = _kstatus.substr(14,1); if(!XString<short>::convertFromString(tmp)) argout += "Data Store : Conversion Rate\n"; else if(XString<short>::convertFromString(tmp) == 1) argout += "Data Store : 1 RDG/Sec\n"; else if(XString<short>::convertFromString(tmp) == 2) argout += "Data Store : 1 RDG/10Sec\n"; else if(XString<short>::convertFromString(tmp) == 3) argout += "Data Store : 1 RDG/Min\n"; else if(XString<short>::convertFromString(tmp) == 4) argout += "Data Store : 1 RDG/10Min\n"; else if(XString<short>::convertFromString(tmp) == 5) argout += "Data Store : 1 RDG/1Hr\n"; else if(XString<short>::convertFromString(tmp) == 6) argout += "Data Store : Trig Button\n"; else if(XString<short>::convertFromString(tmp) == 7) argout += "Data Store : Disabled\n"; //- SRQ Mask tmp = _kstatus.substr(15,2); if(!XString<short>::convertFromString(tmp)) argout += "SRQ Data Mask : SRQ Disabled\n"; else if(XString<short>::convertFromString(tmp) == 1) argout += "SRQ Data Mask : Reading Overflow\n"; else if(XString<short>::convertFromString(tmp) == 2) argout += "SRQ Data Mask : Data Store Full\n"; else if(XString<short>::convertFromString(tmp) == 8) argout += "SRQ Data Mask : Reading Done\n"; else if(XString<short>::convertFromString(tmp) == 16) argout += "SRQ Data Mask : Ready\n"; else if(XString<short>::convertFromString(tmp) == 32) argout += "SRQ Data Mask : Error\n"; //- EOI & Bus Hold Off tmp = _kstatus.substr(17,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"; } catch(std::out_of_range) { set_electroState(ALARM); throw electrometer::ElectrometerException("OUT_OF_RANGE", "Cannot extract device status [find or substr failed !].", "Keithley_617::get_configuration( )."); } set_electroState(ON); return argout; }