/******************************************************************************
 *                                                                         
 *               Copyright 2004-2006 Agilent Technologies
 *               All rights reserved.
 *
 *****************************************************************************/
 
#include "stdafx.h"
#include "CoAgilent34980A.h"

/// <summary>
/// Returns when all pending operations are complete or MaxTimeMilliseconds period is exceeded.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="MaxTimeMilliseconds">
///	Timeout in milliseconds.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_WaitForOperationComplete(long MaxTimeMilliseconds)
{
	HRESULT hr = S_OK;

	long lComplete = -1;

	if (MaxTimeMilliseconds < 100) 
		MaxTimeMilliseconds = 100;  // 100mS minimum.

	// Do not test hr as InstrQuery() may call PollInstrumentError() which may return
	// E_FAIL even though *OPC? returned a 1 before MaxTimeMilliseconds is exceeded.

	// Disable polling if enabled as otherwise InstrQuery() will poll.
	// There is not a "NoPoll" version of InstrQuery().
	VARIANT_BOOL bQueryStatusEnable = VARIANT_FALSE;
	hr = _IIviDriverOperation::get_QueryInstrumentStatus(&bQueryStatusEnable);

	if (FAILED(hr)) 
		return ReportError(IDS_E_IVI_UNEXPECTED_RESPONSE);

	bool bQuerInstrStatusSave = (bQueryStatusEnable != VARIANT_FALSE);

	m_bQueryInstrStatus = false;

	hr = InstrQuery(_T("*OPC?"), &lComplete, MaxTimeMilliseconds);

	if (lComplete == -1) 										// No response from instrument
	{
		hr = ReportError(IDS_E_IVIDMM_MAX_TIME_EXCEEDED,  _T("WaitForOperationComplete"));
	}

	m_bQueryInstrStatus = bQuerInstrStatusSave;

	return hr;
}

/// <summary>
/// Sets the instrument clock.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Hours">
///	The hour in 24-hour clock format.
/// </param>
/// <param name="Mins">
///	The minutes.
/// </param>
/// <param name="Seconds">
///	The seconds, with 1 ms resolution.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_SetSystemTime(long Hours, long Mins, double Seconds)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
/// Sets the instrument calendar.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Year">
///	The current year.
/// </param>
/// <param name="Month">
///	The current month.
/// </param>
/// <param name="Day">
///	The current day.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_SetSystemDate(long Year, long Month, long Day)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
/// Presets the instrument to a known configuration.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
HRESULT Agilent34980A::IAgilent34980ASystem_Preset()
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
/// Returns the instrument clock. The format is hh,mm,ss.sss
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Hours">
///	The hour in 24-hour clock format.
/// </param>
/// <param name="Mins">
///	The minutes.
/// </param>
/// <param name="Seconds">
///	The seconds, with 1 ms resolution.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_GetSystemTime(long* Hours, long* Mins, double* Seconds)
{
	HRESULT hr = S_OK;
	CString sTime, sToken;
	int nPos = 0;
	hr = InstrQueryCommand( sTime, 100 );
	sTime.Remove( '\"' );
	sToken = sTime.Tokenize( ",", nPos );
	*Hours = atol( sToken );

	sToken = sTime.Tokenize( ",", nPos );
	*Mins = atol( sToken );
	
	sToken = sTime.Tokenize( ",", nPos );
	*Seconds = atof( sToken );
	return hr;
}

/// <summary>
/// Returns the date in the form 2004,11,21
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Year">
///	The year.
/// </param>
/// <param name="Month">
///	The month.
/// </param>
/// <param name="Day">
///	The day.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_GetSystemDate(long* Year, long* Month, long* Day)
{
	HRESULT hr = S_OK;

	CString sTime, sToken;
	int nPos = 0;

	hr = InstrQueryCommand( sTime, 100 );
	if( FAILED(hr) ) return hr;
	sTime.Remove( '\"' );
	sToken = sTime.Tokenize( ",", nPos );
	*Year = atol( sToken );

	sToken = sTime.Tokenize( ",", nPos );
	*Month = atol( sToken );
	
	sToken = sTime.Tokenize( ",", nPos );
	*Day = atol( sToken );

	return hr;
}


/// <summary>
/// Resets the module in the specified slot to its power-on state.
/// </summary>
/// <remarks>
/// This method is also used to restore normal operation to a 34925 FET Multiplexer
/// that is in the overvoltage state.
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNum">
///	Slot at which resides the card to reset.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_CardReset(long SlotNum)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Enables or disables asynchronos events.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_AsyncEventsEnabled(VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;
	hr = get_EventEnable(Val);

	return hr;
}


/// <summary>
///	Enables or disables asynchronos events.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_AsyncEventsEnabled(VARIANT_BOOL Val)
{
	HRESULT hr = S_OK;

	hr = put_EventEnable(Val);

	return hr;
}

/// <summary>
///	Returns the identity of the module in the specified slot.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="SlotNum">
///	Slot at which resides the card to query.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_get_CardType(long SlotNum, BSTR* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(Val);

	return hr;
}

/// <summary>
///	Sets or gets the instrument calendar.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_Date(BSTR* Val)
{
	HRESULT hr = S_OK;

	CString sResponse;
	hr = InstrQueryCommand( sResponse, DEFAULT_STRING_LENGTH );
	sResponse.Remove( '\"' );
	*Val = sResponse.AllocSysString();

	return hr;
}

/// <summary>
///	Sets or gets the instrument calendar.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_Date(BSTR Val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Enables or disables the internal DMM.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_DMMEnabled(VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommandBool(Val);

	return hr;
}

/// <summary>
///	Enables or disables the internal DMM.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_DMMEnabled(VARIANT_BOOL Val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Queries the instrument to determine if the internal DMM is installed.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_DMMInstalled(VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommandBool(Val);

	return hr;
}

/// <summary>
///	Enables or disables the instrument to set the Memory Threshold bit in the event
/// register when the specified number of readings have been stored in reading memory
/// during a scan.
/// </summary>
/// <remarks>
///	The number can be anywhere between 1 and 50,000 readings.
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_ReadingThreshold(long* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(Val);

	return hr;
}

/// <summary>
///	Enables or disables the instrument to set the Memory Threshold bit in the event
/// register when the specified number of readings have been stored in reading memory
/// during a scan.
/// </summary>
/// <remarks>
///	The number can be anywhere between 1 and 50,000 readings.
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_ReadingThreshold(long Val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Gets the instrument serial number
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_SerialNumber(BSTR* Val)
{
	HRESULT hr = S_OK;

	*Val = CComBSTR(GetSerialNumber()).Detach();

	return hr;
}

/// <summary>
///	Sets or gets the instrument clock time as a string in format hh,mm,ss.sss.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_Time(BSTR* Val)
{
	HRESULT hr = S_OK;

	CString sResponse;
	hr = InstrQueryCommand( sResponse, DEFAULT_STRING_LENGTH );
	sResponse.Remove( '\"' );
	*Val = sResponse.AllocSysString();

	return hr;
}

/// <summary>
///	Sets or gets the instrument clock time as a string in format hh,mm,ss.sss.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_Time(BSTR Val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Sets or gets the number of milliseconds before a query will timeout.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_TimeoutMilliseconds(long* Val)
{
	HRESULT hr = S_OK;

	hr = ioprvGetIOTimeout( Val );
	
	return hr;
}

/// <summary>
///	Sets or gets the number of milliseconds before a query will timeout.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_put_TimeoutMilliseconds(long Val)
{
	HRESULT hr = S_OK;

	if(Val < 100) Val = 100;  // 100ms minimum.

	hr = ioprvSetIOTimeout( Val );

	return hr;
}

/// <summary>
///	Retrieves a pointer to the IFormattedIO488 interface.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_IO(IFormattedIO488 **Val)
{
	HRESULT hr = S_OK;

	hr = ioprvGetIFormattedIO488Pointer( Val );

	return hr;
}


/// <summary>
///	Disables or enables the GPIB, USB, or LAN remote interfaces. In addition, this
/// command disables or enables the available remote services such as Sockets, Telnet,
/// VXI-11, and the 34980's built-in Web Interface.
/// </summary>
/// <remarks>
///	Send true to enable, false to disable. If the LAN interface is disabled
/// (false), then VXI-11, Sockets, Telnet, and Web are also disabled.
/// </remarks>
/// <param name="HWInterface">
///	One of the Agilent34980AHWInterfaceEnum choices (GPIB, USB, LAN, VXI-11, Sockets,
/// Telnet, and Web).
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_get_EnableInterface(Agilent34980AHWInterfaceEnum HWInterface, VARIANT_BOOL* val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommandBool(val);

	return hr;
}

/// <summary>
///	Disables or enables the GPIB, USB, or LAN remote interfaces. In addition, this
/// command disables or enables the available remote services such as Sockets, Telnet,
/// VXI-11, and the 34980's built-in Web Interface.
/// </summary>
/// <remarks>
///	Send true to enable, false to disable. If the LAN interface is disabled
/// (false), then VXI-11, Sockets, Telnet, and Web are also disabled.
/// </remarks>
/// <param name="HWInterface">
///	One of the Agilent34980AHWInterfaceEnum choices (GPIB, USB, LAN, VXI-11, Sockets,
/// Telnet, and Web).
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_put_EnableInterface(Agilent34980AHWInterfaceEnum HWInterface, VARIANT_BOOL val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}


/// <summary>
/// Requests a lock on the instrument.  If granted, a 1 is returned, otherwise a
/// 0 is returned.
/// </summary>
/// <remarks>
/// When a lock is obtained, only the requesting interface will be allowed to change
/// settings on the instrument.  The other interfaces may query settings on the
/// instrument, but no changes are allowed.  If a requestor asks for, and is granted
/// multiple locks, the requestor must call LockRelease once for each granted request
/// to free the instrument lock(s).
/// </remarks>
/// <returns>	
///	TRUE if successful, otherwise FALSE.
/// </returns>
HRESULT Agilent34980A::IAgilent34980ASystem_LockRequest(VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;

	CString sResp;
	RETURN_IF_FAIL( InstrQueryCommand( sResp, DEFAULT_STRING_LENGTH ) );
	sResp.Remove( '+' );
	if( sResp=='1' )
		*Val = VARIANT_TRUE;
	else
		*Val = VARIANT_FALSE;
	return hr;
}

/// <summary>
/// Releases a lock on the IO interface from which this command is executed, and
/// decrements the lock count by 1.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
HRESULT Agilent34980A::IAgilent34980ASystem_LockRelease()
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Returns a string containing the IO interface that currently has the lock.
/// </summary>
/// <remarks>
///	If no interfaces have a lock, then NONE is returned.  Besides NONE, other return
/// values are GPIB, VXI11, USB, or LAN (IP Address).
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_LockOwner(BSTR* val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(val);

	return hr;
}

/// <summary>
/// This method clears all instrument memory except for boot parameters and stored
/// calibration constants.
/// </summary>
/// <remarks>
/// This method is not recommended for use in routine applications.  This command
/// is typically used to clear all memory before removing the instrument from a
/// secure area.
/// </remarks>
/// <returns>
///	
/// </returns>
HRESULT Agilent34980A::IAgilent34980ASystem_SecureImmediate()
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}





/// <summary>
///	Configures the specified module for 2-wire (differential) or 1-wire (single
/// ended) operation.
/// </summary>
/// <remarks>
///	This property is used only by the 34923 reed multiplexer, the 34925 FET multiplexer,
/// and the 34933 Dual 4x8 reed multiplexer. Mainframe power must be cycled in order
/// for the new setting to take effect. Driver also must be closed and initialized
/// again so that the IIviSwtch functionality can work properly.
/// </remarks>
/// <param name="SlotNumber">
///	Value of 1 to 8.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_put_ModuleWireMode(long SlotNumber, Agilent34980AWireModeEnum val)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}


/// <summary>
///	Reads one event from the instrument Module Event Queue.
/// </summary>
/// <remarks>
///	Only one event is returned per call.  If there are no events, a NULL string
/// is returned, otherwise, a quoted string containing the event description, date,
/// and time of day is returned.
/// </remarks>
HRESULT Agilent34980A::IAgilent34980ASystem_get_ModuleEvents(BSTR* val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(val);

	return hr;
}

/// <summary>
/// Reads either the factory temperature threshold setting or the actual transducer
/// temperature on a GP switch module.
/// </summary>
/// <remarks>
/// This method is only used with the 34937 and 34938 General Purpose relay modules.
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Mode">
///	Selects whether the temperature transducer the factory-set temperature threshold
/// will be returned.
/// </param>
/// <param name="Slot">
///	Slot number (1 to 8) where the 34937 or 34938 is located.
/// </param>
HRESULT Agilent34980A::IAgilent34980ASystem_GetModuleTemperature(Agilent34980AModuleTemperatureEnum Mode, long Slot, double* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand( Val );

	return hr;
}
