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


/// <summary>
/// Configures the Function, Range, and Resolution properties.  If the value of
/// the Range parameter is Auto Range On, then the Resolution parameter is ignored.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Function">
///	Determines the units for the Range and Resolution Absolute parameters, and the
/// measurement values that are returned by the Read, Read Multiple Point, Fetch,
/// and Fetch Multiple Point methods.
/// </param>
/// <param name="Range">
///	The measurement range. Positive values represent the absolute value of the maximum
/// measurement expected. The driver coerces this value to the appropriate range
/// for the instrument. Negative values represent the Auto Range mode.
/// </param>
/// <param name="Resolution">
///	The measurement resolution in absolute units.
/// </param>
HRESULT Agilent34980A::IIviDmm_Configure(IviDmmFunctionEnum Function, double Range, double Resolution)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	The measurement function.  This property determines the units for Range and
/// Resolution and the values returned by the Read, Read Multiple Point, Fetch,
/// and Fetch Multiple Point methods.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Function(IviDmmFunctionEnum* Val)
{
	HRESULT hr = S_OK;
//* comment when IviDmmFunctionEnum is supported in EnumToString
	CString sFunc;
	hr = _GetInstrFunction( sFunc );
	if( FAILED(hr) ) return hr;

	sFunc.MakeUpper(); // make sure it's uppercase
	if( sFunc == "CURR:AC" )
		*Val = IviDmmFunctionACCurrent;
	else if( sFunc == "CURR" )
		*Val = IviDmmFunctionDCCurrent;
	else if( sFunc == "VOLT:AC" )
		*Val = IviDmmFunctionACVolts;
	else if( sFunc == "VOLT" )
		*Val = IviDmmFunctionDCVolts;
	else if( sFunc == "RES" )
		*Val = IviDmmFunction2WireRes;
	else if( sFunc == "FRES" )
		*Val = IviDmmFunction4WireRes;
	else if( sFunc == "PER" )
		*Val = IviDmmFunctionPeriod;
	else if( sFunc == "FREQ" )
		*Val = IviDmmFunctionFreq;
 // so far instrument does not take these:

	//else if( sFunc == "DIG" )
	//	*Val = IviDmmFunction;
	//else if( sFunc == "TEMP" )
	//	*Val = IviDmmFunctionTemperature;
	//else if( sFunc == "TOT" )
	//	*Val = IviDmmFunction;

	//*Val = EnumFromString( sFunc ); add when this enum is supported 
	return hr;
}

/// <summary>
///	The measurement function.  This property determines the units for Range and
/// Resolution and the values returned by the Read, Read Multiple Point, Fetch,
/// and Fetch Multiple Point methods.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_put_Function(IviDmmFunctionEnum Val)
{
	HRESULT hr = S_OK;
	//[:SENSe]:FUNCtion <function_type> i.e. FUNC "VOLT"
	CString sCmd;
	switch( Val )
	{
	case IviDmmFunctionACCurrent:	sCmd = "FUNC \"CURR:AC\"";	break;
	case IviDmmFunctionDCCurrent:	sCmd = "FUNC \"CURR\"";		break;
	case IviDmmFunctionACVolts:		sCmd = "FUNC \"VOLT:AC\"";	break;	
	case IviDmmFunctionDCVolts:		sCmd = "FUNC \"VOLT\"";		break;
	case IviDmmFunction2WireRes:	sCmd = "FUNC \"RES\"";		break;
	case IviDmmFunction4WireRes:	sCmd = "FUNC \"FRES\"";		break;
	case IviDmmFunctionPeriod:		sCmd = "FUNC \"PER\"";		break;
	case IviDmmFunctionFreq:		sCmd = "FUNC \"FREQ\"";		break;	
	case IviDmmFunctionTemperature:	sCmd = "FUNC \"TEMP\"";		break;
//	case 
	default: return E_INVALIDARG;
	}
	hr = InstrWrite( sCmd );
	return hr;
}

/// <summary>
///	The measurement range, coerced by the driver to the appropriate range for the
/// instrument.  Positive values set the absolute value of the maximum measurement
/// expected.  Negative values set Auto Range mode.  Units are determined by Function.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Range(double* Val)
{
	if( ! Val ) return E_POINTER;
	HRESULT hr = S_OK;
	//[:SENSe]:<function_type>:RANGe?
	CString sFunc, sCmd;
	long l = 0;// int n = 0;
	hr = _GetInstrFunction( sFunc ); // IIviDmm_get_Function converts to enum; we need the string so DIY
	if( FAILED(hr))
		return hr;
	double dRange;
	sCmd = sFunc+":RANG?";
	InstrQuery( sCmd, &dRange );
	sCmd = sFunc+":RANG:AUTO?";
	InstrQuery( sCmd, &l );
	*Val = (l==1) ? -dRange : dRange;
	return hr;
}

/// <summary>
///	The measurement range, coerced by the driver to the appropriate range for the
/// instrument.  Positive values set the absolute value of the maximum measurement
/// expected.  Negative values set Auto Range mode.  Units are determined by Function.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_put_Range(double Val)
{
	HRESULT hr = S_OK;

	//[:SENSe]:<function_type>:RANGe
	CString sFunc, sVal, sCmd;
	hr = _GetInstrFunction( sFunc );
	if(FAILED(hr)) return hr;
	sCmd = sFunc + ":RANG ";
	sVal.Format( "%f", (Val>0) ? Val : -Val );
	sCmd += sVal;
	hr = InstrWrite(sCmd);
	if(FAILED(hr)) return hr;
	 // so far, instrument does not switch to :RANG:AUTO properly according to range sign, so do it explicitly
	sCmd = sFunc + ( Val>0 ? ":RANG:AUTO 0" : ":RANG:AUTO 1" );
	
	return InstrWrite(sCmd);
}

/// <summary>
///	The measurement resolution in absolute units.  Units are determined by Function.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Resolution(double* Val)
{
	HRESULT hr = S_OK;

	CString sFunc, sVal;
	int l = 0;
	hr = InstrQuery( "CONF?", sFunc, DEFAULT_STRING_LENGTH );
	if( FAILED(hr))	return hr;
	sFunc.Tokenize( " ,", l ); sFunc.Tokenize( " ,", l );
	sVal = sFunc.Tokenize( " ,", l ); // resolution is the 3rd token in response
	*Val = atof( sVal );

	return hr;
}

/// <summary>
///	The measurement resolution in absolute units.  Units are determined by Function.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_put_Resolution(double Val)
{
	HRESULT hr = S_OK;

	CString sFunc, sVal;
	hr = _GetInstrFunction( sFunc );
	if(FAILED(hr)) return hr;
	sFunc += ":RES ";
	sVal.Format( " %f", Val );
	sFunc += sVal;
	
	return InstrWrite(sFunc);
}

/// <summary>
///	Pointer to the class-compliant IIviDmmAc interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_AC(IIviDmmAC** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}

/// <summary>
///	Pointer to the class-compliant IIviDmmAdvanced interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Advanced(IIviDmmAdvanced** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}

/// <summary>
///	Pointer to the class-compliant IIviDmmFrequency interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Frequency(IIviDmmFrequency** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}

/// <summary>
///	Pointer to the class-compliant IIviDmmMeasurement interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Measurement(IIviDmmMeasurement** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}

/// <summary>
///	Pointer to the class-compliant IIviDmmTemperature interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Temperature(IIviDmmTemperature** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}

/// <summary>
///	Pointer to the class-compliant IIviDmmTrigger interface
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IIviDmm_get_Trigger(IIviDmmTrigger** Val)
{
	HRESULT hr = S_OK;

	hr = InternalQueryInterface(this, _GetEntries(), __uuidof(*Val), reinterpret_cast<void**>(Val));

	return hr;
}


