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



/// <summary>
/// Configures the specified channels for 4-wire measurements but do not initiate
///  the scan.
/// </summary>
/// <remarks>
/// If you supply empty ChannelList this method applies to the internal DMM, independent
///  of any channels or a scan list.
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="ChannelList">
///	One or more channels in the form sccc.
/// </param>
/// <param name="Range">
///	Enter the expected signal value.  Actual ranges available on the instrument
/// are 100, 1,000, 10,000, 100,000, 1 M, 10 M, and 100 M Ohms. If the range value
/// specified is negative, AUTO ranging will be enabled.
/// </param>
/// <param name="Resolution">
///	Select from Least (4.5 digits), DEFault (5.5 digits) and Best (6.5 digits).
/// The resolution is controlled by the NPLC property, and there are several more
/// settings than the 3 offered here.  See the NPLC property on this interface to
/// choose a more specific resolution setting, and to see the trade offs in measurement
/// speed vs. resolution (accuracy).
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_Configure(BSTR ChannelList, double Range, Agilent34980AResolutionEnum Resolution)
{
	HRESULT hr = S_OK;

	CString sList = CorrectChannelList( ChannelList );

	if( Range<0 )
	{ // get rid of neg sign
		CString sCmd = PopInstrCommand();
		sCmd.Delete( sCmd.Find( '-' ) );
		PushInstrCommand( sCmd );
		hr = InstrPrintCommand();
		if( ::SysStringLen( ChannelList ) )
		{
			RETURN_IF_FAIL( InstrPrintf( "FRES:RANG:AUTO 1, (@%s)", sList ) );
		}
		else
		{
			RETURN_IF_FAIL( InstrPrintf( "FRES:RANG:AUTO 1" ) );
		}
	}
	else
	{
		hr = InstrPrintCommand();
	}

	return hr;
}

/// <summary>
///	Sets or gets the measurement acquisition time (called integration time) in seconds.
/// </summary>
/// <remarks>
///	By default, this setting is not used unless directly set by the user.  Allowable
/// values are from 300E-6 seconds to 1 second with 4E-6 second resolution. \r\n
/// NOTE: You should use this command only when you want precise control of the
/// integration time of the internal DMM. Otherwise, specifying integration time
/// using NPLC executes faster and offers better noise rejection characteristics
/// for values of NPLC greater than 1.  \r\n
/// If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_Aperture(BSTR ChannelList, double* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_Aperture"), _T("ChannelList"));
	}
	CorrectChannelList( ChannelList, false );
	hr = InstrQueryCommand(Val);

	return hr;
}

/// <summary>
///	Sets or gets the measurement acquisition time (called integration time) in seconds.
/// </summary>
/// <remarks>
///	By default, this setting is not used unless directly set by the user.  Allowable
/// values are from 300E-6 seconds to 1 second with 4E-6 second resolution. \r\n
/// NOTE: You should use this command only when you want precise control of the
/// integration time of the internal DMM. Otherwise, specifying integration time
/// using NPLC executes faster and offers better noise rejection characteristics
/// for values of NPLC greater than 1.  \r\n
/// If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_put_Aperture(BSTR ChannelList, double Val)
{
	HRESULT hr = S_OK;

	CorrectChannelList( ChannelList );

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Enables/Disables autoranging on the specified channel.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_AutoRange(BSTR ChannelList, VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_AutoRange"), _T("ChannelList"));
	}
	CorrectChannelList( ChannelList, false );
	hr = InstrQueryCommandBool(Val);

	return hr;
}

/// <summary>
///	Enables/Disables autoranging on the specified channel.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_put_AutoRange(BSTR ChannelList, VARIANT_BOOL Val)
{
	HRESULT hr = S_OK;

	CorrectChannelList( ChannelList );

 	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Sets or gets the measurement acquisition time (called integration time) in number
/// of power line cycles (PLCs) on the specified channels.
/// </summary>
/// <remarks>
/// Repeatable measurement accuracy is obtained by measuring in multiples of the
/// power line frequency; this eliminates noise injected by the power supply that
/// may be embedded inside the signal being measured.  The NPLC setting affects
/// the measurement resolution (for better resolution, use a larger NPLC value)
/// and measurement speed (for faster measurements, use a smaller NPLC value). 
/// The resolution settings from Configure and Measure routines map directly to
/// NPLC settings: BEST = 200 NPLC, LEAST = 0.02 NPLC, and DEFAULT = 1 NPLC. See
/// below for the measurement accuracies obtained with the various NPLC settings.
/// \r\n
/// If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_NPLC(BSTR ChannelList, double* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_NPLC"), _T("ChannelList"));
	}
	CorrectChannelList( ChannelList, false );
	hr = InstrQueryCommand(Val);

	return hr;
}

/// <summary>
///	Sets or gets the measurement acquisition time (called integration time) in number
/// of power line cycles (PLCs) on the specified channels.
/// </summary>
/// <remarks>
/// Repeatable measurement accuracy is obtained by measuring in multiples of the
/// power line frequency; this eliminates noise injected by the power supply that
/// may be embedded inside the signal being measured.  The NPLC setting affects
/// the measurement resolution (for better resolution, use a larger NPLC value)
/// and measurement speed (for faster measurements, use a smaller NPLC value). 
/// The resolution settings from Configure and Measure routines map directly to
/// NPLC settings: BEST = 200 NPLC, LEAST = 0.02 NPLC, and DEFAULT = 1 NPLC. See
/// below for the measurement accuracies obtained with the various NPLC settings.\r\n
///	|--------------------------------------------------------------------|\r\n
///	| Integration Time |     Resolution               |  Digits  | Bits  |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 0.02 PLC         | less than 0.0001 x Range     | 4 Digits |  15   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 0.2 PLC          | less than 0.00001 x Range    | 5 Digits |  18   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 1 PLC            | less than 0.000003  x Range  | 5 Digits |  20   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 2 PLC            | less than 0.0000022 x Range  | 6 Digits |  21   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 10 PLC           | less than 0.000001 x Range   | 6 Digits |  24   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 20 PLC           | less than 0.0000008 x Range  | 6 Digits |  25   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 100 PLC          | less than 0.0000003 x Range  | 6 Digits |  26   |\r\n
///	|--------------------------------------------------------------------|\r\n
///	| 200 PLC          | less than 0.00000022 x Range | 6 Digits |  26   |\r\n
///	|--------------------------------------------------------------------|
/// If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_put_NPLC(BSTR ChannelList, double Val)
{
	HRESULT hr = S_OK;

	CorrectChannelList( ChannelList );

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Enables or disables offset compensation.
/// </summary>
/// <remarks>
///	Offset compensation removes the effects of any dc voltages in the circuit being
/// measured. The technique involves taking the difference between two resistance
/// measurements on the specified channels, one with the current source turned on
/// and one with the current source turned off. If the ChannelList parameter is
/// empty, this command applies to the internal DMM, independent of any channels
/// or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_OCompensated(BSTR ChannelList, VARIANT_BOOL* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_OCompensated"), _T("ChannelList"));
	}
	CorrectChannelList( ChannelList, false );
	hr = InstrQueryCommandBool(Val);

	return hr;
}

/// <summary>
///	Enables or disables offset compensation.
/// </summary>
/// <remarks>
///	Offset compensation removes the effects of any dc voltages in the circuit being
/// measured. The technique involves taking the difference between two resistance
/// measurements on the specified channels, one with the current source turned on
/// and one with the current source turned off. If the ChannelList parameter is
/// empty, this command applies to the internal DMM, independent of any channels
/// or a scan list.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_put_OCompensated(BSTR ChannelList, VARIANT_BOOL Val)
{
	HRESULT hr = S_OK;

	CorrectChannelList( ChannelList );

 	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	Selects the measurement range on the specified channel.
/// </summary>
/// <remarks>
///	If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.\r\n
/// The following ranges are available:  100O (MIN), 1 kO, 10 kO, 100 kO, 1 MO,
/// 10 MO, 100 MO (MAX).
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_Range(BSTR ChannelList, double* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_Range"), _T("ChannelList"));
	}
	sList = CorrectChannelList( ChannelList, false );
	RETURN_IF_FAIL( InstrQueryCommand(Val) );
	long lAuto;
	if( ::SysStringLen( ChannelList ) )
		hr = InstrQueryf( "FRES:RANG:AUTO? (@%s)", &lAuto, sList );
	else
		hr = InstrQuery( "FRES:RANG:AUTO?", &lAuto );
	if( lAuto )
		*Val = -(*Val);

	return hr;
}

/// <summary>
///	Selects the measurement range on the specified channel.
/// </summary>
/// <remarks>
///	If the ChannelList parameter is empty, this command applies to the internal
/// DMM, independent of any channels or a scan list.\r\n
/// The following ranges are available:  100O (MIN), 1 kO, 10 kO, 100 kO, 1 MO,
/// 10 MO, 100 MO (MAX).
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_put_Range(BSTR ChannelList, double Val)
{
	HRESULT hr = S_OK;

	CString sList = CorrectChannelList( ChannelList );

	RETURN_IF_FAIL( InstrPrintCommand() );
	if( Val<0 )
	{ // get rid of neg sign
		CString sCmd = PopInstrCommand();
		sCmd.Delete( sCmd.Find( '-' ) );
		PushInstrCommand( sCmd );
		if( ::SysStringLen( ChannelList ) )
		{
			RETURN_IF_FAIL( InstrPrintf( "FRES:RANG:AUTO 1, (@%s)", sList ) );
		}
		else
		{
			RETURN_IF_FAIL( InstrPrintf( "FRES:RANG:AUTO 1" ) ); 
		}
	}
	hr = InstrPrintCommand();

	return hr;
}





/// <summary>
///	Sets or gets the resolution on the specified channel.
/// </summary>
/// <remarks>
///	Resolution may be set by using the NPLC property, see the NPLC property for
/// details.
/// </remarks>
/// <param name="ChannelList">
///	One or more channels in the form sccc. Must contain only 1 entry for the getter.
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_get_Resolution(BSTR ChannelList, double* Val)
{
	HRESULT hr = S_OK;

	CString sList(ChannelList);
	if( -1 != sList.Find( ',' ) || -1!=sList.Find( ':' ) || -1 != sList.Find( '-' ) )
	{
		return ReportError( E_AGILENT34980A_MULTIPLE_CHANNELS_IN_GET, _T("IAgilent34980AFResistance_get_Resolution"), _T("ChannelList"));
	}
	CorrectChannelList( ChannelList, false );
	hr = InstrQueryCommand(Val);

	return hr;
}



/// <summary>
/// Resets all measurement parameters on the specified channels to their default
///  values. Then, configures the channels for 4-wire resistance measurements and
/// immediately sweeps through the specified  channels one time    (channels in
/// Bank 1 are automatically paired with corresponding channels in  Bank 2).
/// </summary>
/// <remarks>
/// The results are sent directly to the instrument's output buffer. If you supply
///  empty ChannelList, this this method applies to the internal DMM,    independent
/// applies to the internal DMM, independent of any channels or a scan  list.
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="ChannelList">
///	One or more channels in the form sccc.
/// </param>
/// <param name="Range">
///	Enter the expected signal value.  Actual ranges available on the instrument
/// are 100, 1,000, 10,000, 100,000, 1 M, 10 M, and 100 M Ohms.  If the range value
/// specified is negative, AUTO ranging will be enabled.
/// </param>
/// <param name="Resolution">
///	Select from Least (4.5 digits), DEFault (5.5 digits) and Best (6.5 digits).
/// The resolution is controlled by the NPLC property, and there are several more
/// settings than the 3 offered here. See the NPLC property on this interface to
/// choose a more specific resolution setting, and to see the trade offs in measurement
/// speed vs. resolution (accuracy).
/// </param>
HRESULT Agilent34980A::IAgilent34980AFResistance_Measure(BSTR ChannelList, double Range, Agilent34980AResolutionEnum Resolution, SAFEARRAY** val)
{
	HRESULT hr = S_OK;

	CString sList = CorrectChannelList( ChannelList );

	if( Range<0 )
	{ // get rid of neg sign
		CString sCmd = PopInstrCommand();
		sCmd.Delete( sCmd.Find( '-' ) );
		PushInstrCommand( sCmd );
		// prepare new command for AUTO ranging
		PopInstrCommand();
		sCmd.Format("MEAS:FRES? AUTO, %s, (@%s)", EnumToString<Agilent34980AResolutionEnum>(Resolution), sList );
		PushInstrCommand( sCmd ); // pop is in ForwardingShims.h
	}
	RETURN_IF_FAIL( InstrPrintCommandNoPoll() );

	hr = FormattedReadList( NtlAsciiType_R8, ",", val );

	return hr;
}
