//>>*************************************************************************** // UNCLASSIFIED // // COPYRIGHT 2017 RAYTHEON MISSILE SYSTEMS // ALL RIGHTS RESERVED // This data was developed pursuant to Contract Number HQ0147-12-C-0004/1088370 // with the US Government. The US Government's rights in and to this // copyrighted data are as specified in DFAR 252.227-7013 // which was made part of the above contract. // // Distribution Statement: D -Distribution authorized to the DoD and DoD // contractors only based on Critical Technology Requirements, May 2001. // Other requests shall be referred to PEO THEATER AIR DEFENSE (PMS 422). // Warning: - This document contains technical data whose export is restricted // by the Arms Export Control Act (Title 22, U.S.C.) or Export // Administration Act of 1979, as amended (Title 50, U.S.C.). Violations // of these laws are subject to severe criminal penalties. Disseminate in // accordance with provisions of DoD 5230.25. // Destruction Notice: - For unclassified, limited distribution information, // destroy by any method that will prevent disclosure of contents or // reconstruction of the document. Classified information, destroy in // accordance with DoD-5220.22-M or OPNAVINST 5510.1h. //>>*************************************************************************** using System; using System.Net.Sockets; using System.Text; using System.Threading; using NLog; using Raytheon.Common; using Raytheon.Framework; namespace Raytheon.Instruments { /// /// public class SigGenKeysightScpi : ISignalGenerator { #region PublicMembers #endregion #region PrivateMembers private const string _READ_ERROR_CODE_CMD = "SYST:ERR?"; private const string _SELFTESTCMD = "*TST? "; private const string _RESETCMD = "*RST"; private const string _ISOPCCMD = "*STB? "; private const string _FREQCMD = ":FREQ:FIX"; private const string _PWRLEVELMD = "POW:LEV"; private const string _OUTPUTON = ":OUTPut ON"; private const string _OUTPUTOFF = ":OUTPut OFF"; private int m_PORT = 5025; private const int m_READ_TIMEOUT = 5000; private readonly string _address; private byte[] _readBuffer; private NetworkStream _tcpStream; private State _state; private SelfTestResult _selfTestResult; private string _name; private readonly ILogger _logger; private readonly IConfigurationManager _configurationManager; private readonly IConfiguration _configuration; #endregion #region PrivateFunctions /// /// The Finalizer which will release resources if required /// ~SigGenKeysightScpi() { Dispose(false); } /// /// Convert scpi data to string /// /// /// private string ConvertToString(ref byte[] data) { string rsp = System.Text.Encoding.ASCII.GetString(data); return rsp; } /// /// Dispose of this object /// /// protected virtual void Dispose(bool disposing) { if (disposing) { if (_state == State.Ready) { Reset(); _tcpStream.Close(); _tcpStream.Dispose(); _state = State.Uninitialized; } } } /// /// Get the error code. /// /// The error code. /// The error description. private string GetErrorCode(out int errorCode) { // not calling IOQuery() here so IOQuery() can call GetErrorCode() after each query string command = _READ_ERROR_CODE_CMD + "\n"; byte[] commandBuffer = Encoding.ASCII.GetBytes(command); // send the data out _tcpStream.Write(commandBuffer, 0, commandBuffer.Length); // clear our buffer Array.Clear(_readBuffer, 0, _readBuffer.Length); // read the response int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length); // convert to a string string rspStr = ConvertToString(ref _readBuffer); // parse the response string[] tokens = rspStr.Split(','); errorCode = Util.ConvertStringToInt32(tokens[0]); // it should always be 2 if (tokens.Length >= 2) { return tokens[1]; } else { return ""; } } /// /// /// /// /// /// private bool IsOperationCompleted(string statusString, string expectedResult = "1") { bool completed = false; // If Scope returns '+x' instead of 'x', where 'x' is any character, trim it. if (statusString.IndexOf('+') == 0) { statusString = statusString.TrimStart('+'); } if (statusString.Equals(expectedResult) == true) { completed = true; } return completed; } #endregion /// /// SigGenKeysightScpi factory constructor /// /// /// public SigGenKeysightScpi(string deviceName, IConfigurationManager configurationManager) { const int READ_BUFFER_SIZE = 512; Name = deviceName; _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}"); _configurationManager = configurationManager; _configuration = _configurationManager.GetConfiguration(Name); _address = _configuration.GetConfigurationValue("SigGenKeysightScpi", "Address", "127.0.0.1"); m_PORT = _configuration.GetConfigurationValue("SigGenKeysightScpi", "Port", 5025); _readBuffer = new byte[READ_BUFFER_SIZE]; TcpClient scopeSocketConn = new TcpClient(_address, m_PORT); _tcpStream = scopeSocketConn.GetStream(); _tcpStream.ReadTimeout = m_READ_TIMEOUT; _state = State.Uninitialized; _selfTestResult = SelfTestResult.Unknown; } /// /// /// /// /// public SigGenKeysightScpi(string deviceName, string address) { const int READ_BUFFER_SIZE = 512; _name = deviceName; _logger = LogManager.GetLogger($"{this.GetType().Name} - {deviceName}"); _address = address; _readBuffer = new byte[READ_BUFFER_SIZE]; TcpClient scopeSocketConn = new TcpClient(_address, m_PORT); _tcpStream = scopeSocketConn.GetStream(); _tcpStream.ReadTimeout = m_READ_TIMEOUT; _state = State.Uninitialized; _selfTestResult = SelfTestResult.Unknown; } /// /// /// /// public bool ClearErrors() { throw new NotImplementedException(); } /// /// /// public string DetailedStatus { get { return "This is a Scpi Signal Generator"; } } /// /// /// public bool DisplayEnabled { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// Dispose of this objects resources /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// /// /// /// public void Enable(bool enable) { if (enable == true) { string command = _OUTPUTON + "\n"; IOWrite(command); } else { string command = _OUTPUTOFF + "\n"; IOWrite(command); } } /// /// /// public bool FrontPanelEnabled { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// /// public InstrumentMetadata Info { get { throw new NotImplementedException(); } } /// /// /// public void Initialize() { // if we have not yet been initialized, go ahead and create the socket if (_state == State.Uninitialized) { Reset(); // we already connected to the instrument in the constructor _state = State.Ready; } else { throw new Exception("expected the state of System " + _name + " to be Uninitialized, state was: " + _state.ToString()); } } /// /// /// /// /// public string IOQuery(string command) { // send the command IOWrite(command, false); // clear our buffer Array.Clear(_readBuffer, 0, _readBuffer.Length); // read from the response int numBytesRead = _tcpStream.Read(_readBuffer, 0, _readBuffer.Length); // convert response to a string string rspStr = ConvertToString(ref _readBuffer); // check for errors int err = 0; string message = GetErrorCode(out err); if (err != 0) { throw new Exception("SigGenKeysightScpi:IOQuery() - Sig Gen " + _name + " returned error code: " + err.ToString() + ", " + message); } return rspStr; } /// /// /// /// public void IOWrite(string command, bool shallWeCheckForError = true) { // convert to a byte array byte[] commandBuffer = Encoding.ASCII.GetBytes(command); // send the data out _tcpStream.Write(commandBuffer, 0, commandBuffer.Length); // check for errors if (shallWeCheckForError == true) { int err = 0; string errorMessage = GetErrorCode(out err); if (err != 0) { throw new Exception("SigGenKeysightScpi:IOWrite() - Device " + _name + " returned error code: " + err.ToString() + "," + errorMessage); } } } /// /// /// public string Name { get { return _name; } set { _name = value; } } /// /// /// public SelfTestResult SelfTestResult { get { return _selfTestResult; } } /// /// /// public State Status { get { return _state; } } /// /// /// /// public SelfTestResult PerformSelfTest() { try { // change the timeout to account for the long self test _tcpStream.ReadTimeout = 120000; // send the command and get the rsponse string command = _SELFTESTCMD + "\n"; string rspStr = IOQuery(command); // parse the response string[] tokens = rspStr.Split('\n'); //Check if self test is completed; returns status of "0". if (IsOperationCompleted(tokens[0], "0") == false) { string errorMsg = "System " + _name + " returned an error: " + tokens[0]; throw new Exception(errorMsg); } _selfTestResult = SelfTestResult.Pass; return SelfTestResult.Pass; } catch (Exception) { throw; } finally { // restore the timeout _tcpStream.ReadTimeout = m_READ_TIMEOUT; } } /// /// /// public void Reset() { // Resets the sig gen string command = _RESETCMD + "\n"; IOWrite(command); Thread.Sleep(3000); /*command = _ISOPCCMD + "\n"; string rspStr = IOQuery(command); // parse the response string[] tokens = rspStr.Split('\n'); if (IsOperationCompleted(tokens[0]) == false) { throw new Exception("Reset was not completed."); }*/ } /// /// /// /// /// /// public void SetFrequency(UnitizedValue frequency) { int freq = Convert.ToInt32(frequency.Value); string command = _FREQCMD + " " + freq.ToString() + "\n"; IOWrite(command); } /// /// /// /// public void SetPowerLevel(UnitizedValue powerLevel) { int power = Convert.ToInt32(powerLevel.Value); string command = _PWRLEVELMD + " " + power.ToString() + "dBm\n"; IOWrite(command); } /// /// /// public void Shutdown() { string errorMsg = ""; if (_state == State.Ready) { try { //Reset System Reset(); } catch (Exception err) { errorMsg += err.Message + " "; } _state = State.Uninitialized; } // the stream was created in the constructor, dispose of it here try { if (_tcpStream != null) { _tcpStream.Dispose(); _tcpStream = null; } } catch (Exception err) { errorMsg += err.Message + " "; } if (errorMsg != "") { throw new Exception("System " + _name + " Had an error: " + errorMsg); } } } }