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

/// <summary>
/// Presets the status system
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
HRESULT Agilent34980A::IAgilent34980AStatus_Preset()
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
/// Configures instrument to issue an SRQ on events defined in SRQReasonEnum parameter.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="Reason">
///	Identifies on which events to be issued the SRQ request (values can be OR-ed i.e. multiple bits can be set).
/// </param>
HRESULT Agilent34980A::IAgilent34980AStatus_ConfigureServiceRequest(Agilent34980ASRQReasonEnum Reason)
{
	HRESULT hr = S_OK;

	UINT sre = 0, ese = 0, alarmEnab = 0, quesEnab = 0, operEnab = 0;
	UINT	bit[] =
	{
		0x0001,	0x0002,	0x0004,	0x0008,
		0x0010,	0x0020,	0x0040,	0x0080,
		0x0100,	0x0200,	0x0400,	0x0800,
		0x1000,	0x2000,	0x4000,	0x8000,
	};


	if(Reason & Agilent34980ASRQReasonStbMAV)				sre = sre | bit[4];
	if(Reason & Agilent34980ASRQReasonStbErrorQue)			sre = sre | bit[2];

	if(Reason & Agilent34980ASRQReasonEsrOPC)				{ese = ese | bit[0];sre = sre | bit[5];}
	if(Reason & Agilent34980ASRQReasonEsrQueryError)		{ese = ese | bit[2];sre = sre | bit[5];}
	if(Reason & Agilent34980ASRQReasonEsrDeviceError)		{ese = ese | bit[3];sre = sre | bit[5];}
	if(Reason & Agilent34980ASRQReasonEsrExecutionError)	{ese = ese | bit[4];sre = sre | bit[5];}
	if(Reason & Agilent34980ASRQReasonEsrCommandError)		{ese = ese | bit[5];sre = sre | bit[5];}

	// questionable register
	if(Reason & Agilent34980ASRQReasonQuesVoltage)			{quesEnab = quesEnab | bit[0];sre = sre | bit[3];}
	if(Reason & Agilent34980ASRQReasonQuesCurrent)			{quesEnab = quesEnab | bit[1];sre = sre | bit[3];}
	if(Reason & Agilent34980ASRQReasonQuesResistance)		{quesEnab = quesEnab | bit[9];sre = sre | bit[3];}
	if(Reason & Agilent34980ASRQReasonQuesTemperature)		{quesEnab = quesEnab | bit[10];sre = sre | bit[3];}

	if(Reason & Agilent34980ASRQReasonQuesTotalizer)		{quesEnab = quesEnab | bit[11];sre = sre | bit[3];}
	if(Reason & Agilent34980ASRQReasonQuesMemory)			{quesEnab = quesEnab | bit[12];sre = sre | bit[3];}

	// alarm enable register
	if(Reason & Agilent34980ASRQReasonAlarm1)					{alarmEnab = alarmEnab | bit[0];sre = sre | bit[1];}
	if(Reason & Agilent34980ASRQReasonAlarm2)					{alarmEnab = alarmEnab | bit[1];sre = sre | bit[1];}
	if(Reason & Agilent34980ASRQReasonAlarm3)					{alarmEnab = alarmEnab | bit[2];sre = sre | bit[1];}
	if(Reason & Agilent34980ASRQReasonAlarm4)					{alarmEnab = alarmEnab | bit[3];sre = sre | bit[1];}
	if(Reason & Agilent34980ASRQReasonAlarmQEmpty)			{alarmEnab = alarmEnab | bit[4];sre = sre | bit[1];}
	if(Reason & Agilent34980ASRQReasonAlarmQOV)				{alarmEnab = alarmEnab | bit[5];sre = sre | bit[1];}
	// enable operational register
	if(Reason & Agilent34980ASRQReasonOperScanning)			{operEnab = operEnab | bit[4];sre = sre | bit[7];}
	if(Reason & Agilent34980ASRQReasonOperConfChange)		{operEnab = operEnab | bit[8];sre = sre | bit[7];}
	if(Reason & Agilent34980ASRQReasonOperMemThreshold)	{operEnab = operEnab | bit[9];sre = sre | bit[7];}
									
	// STATus:PRESet			
	// *CLS						
	// *SRE <Bits>
	// *ESE <Bits>
	// STATus:QUEStionable:ENABle <Bits>
	// STATus:OPERation:ENABle <Bits>
	// STATus:OPERation:ENABle <Bits>
	hr = InstrPrintf( "STAT:PRES; *CLS; *SRE %d; *ESE %d; :STAT:QUES:ENAB %d; :STAT:OPER:ENAB %d; :STAT:ALAR:ENAB %d", 
							sre, ese, quesEnab, operEnab, alarmEnab);

	return hr;
}

/// <summary>
/// Clears event registers and error queue.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
HRESULT Agilent34980A::IAgilent34980AStatus_Clear()
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
///	This routine is used enable the propagation of bits from the register specified
/// by parameter 2 (with the exception of the Status Byte register) into a summary
/// bit for the specified register that gets sent on to the Status Byte.  For the
/// Status Byte register, this routine is used to determine which bits in the Status
/// Byte may be enabled to cause a service request. The only legal value for parameter
/// 3 (SubRegister) is ENABLE, because the other choices are not writable registers.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="Register">
///	Specifies the status register.
/// </param>
/// <param name="SubRegister">
///	Specifies the status sub-register.
/// </param>
HRESULT Agilent34980A::IAgilent34980AStatus_get_Register(Agilent34980AStatusRegisterEnum Register, Agilent34980AStatusSubRegisterEnum SubRegister, long* Val)
{
	HRESULT hr = S_OK;

	switch( Register )
	{
		case Agilent34980AStatusRegisterStatusByte:
			// Status byte register only has enable and event registers
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterCondition:	
					hr = InstrQueryf( "*STB?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = InstrQueryf( "*SRE?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			
			break;

		case Agilent34980AStatusRegisterStandardEvent:
			// Standard event register only has enable and event registers
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterEvent:
					hr = InstrQueryf( "*ESR?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = InstrQueryf( "*ESE?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			break;

		case Agilent34980AStatusRegisterOperation:
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterCondition:
					hr = InstrQueryf( "STAT:OPER:COND?", Val );
					break;
				case Agilent34980AStatusSubRegisterEvent:
					hr = InstrQueryf( "STAT:OPER?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = InstrQueryf( "STAT:OPER:ENAB?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			break;

		case Agilent34980AStatusRegisterQuestionable:
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterCondition:
					hr = InstrQueryf( "STAT:QUES:COND?", Val );
					break;
				case Agilent34980AStatusSubRegisterEvent:
					hr = InstrQueryf( "STAT:QUES?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = GetRoot()->InstrQueryf( "STAT:QUES:ENAB?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}			
			break;

		case Agilent34980AStatusRegisterAlarm:
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterCondition:
					hr = InstrQueryf( "STAT:ALAR:COND?", Val );
					break;
				case Agilent34980AStatusSubRegisterEvent:
					hr = InstrQueryf( "STAT:ALAR?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = InstrQueryf( "STAT:ALAR:ENAB?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}			
			break;

		case Agilent34980AStatusRegisterModule:
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterEvent:
					hr = InstrQueryf( "STAT:MOD:EVEN?", Val );
					break;
				case Agilent34980AStatusSubRegisterEnable:
					hr = InstrQueryf( "STAT:MOD:ENAB?", Val );
					break;
				default:
					return ReportInvalidValueError(_T("get_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}			
			break;

		default:
			return ReportInvalidValueError(_T("get_Register"), _T("Register"), (long)(Register));
			break;
	}	

	return hr;
}

/// <summary>
///	This routine is used enable the propagation of bits from the register specified
/// by parameter 2 (with the exception of the Status Byte register) into a summary
/// bit for the specified register that gets sent on to the Status Byte.  For the
/// Status Byte register, this routine is used to determine which bits in the Status
/// Byte may be enabled to cause a service request. The only legal value for parameter
/// 3 (SubRegister) is ENABLE, because the other choices are not writable registers.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="Register">
///	Specifies the status register.
/// </param>
/// <param name="SubRegister">
///	Specifies the status sub-register.
/// </param>
HRESULT Agilent34980A::IAgilent34980AStatus_put_Register(Agilent34980AStatusRegisterEnum Register, Agilent34980AStatusSubRegisterEnum SubRegister, long Val)
{
	HRESULT hr = S_OK;

	CString strCommand;

	switch( Register )
	{
		case Agilent34980AStatusRegisterStatusByte:
			if( SubRegister == Agilent34980AStatusSubRegisterEnable ) {
				// 8-bit register
				// *SRE <Bits>
				Val &= 0xFF;
				hr = InstrPrintf( "*SRE %ld", Val );
			}
			else
				return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
			break;

		case Agilent34980AStatusRegisterStandardEvent:
			// Only the Enable subregister is writable
			if( SubRegister == Agilent34980AStatusSubRegisterEnable ) {
				// 8-bit register
				// *ESE <Bits>
				Val &= 0xFF;
				hr = InstrPrintf( "*ESE %ld", Val );
			}
			else
				return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
			break;

		
		case Agilent34980AStatusRegisterOperation:
			// 16-bit register
			Val &= 0xFFFF;
			// Only the Enable subregister is writable
			switch( SubRegister )
			{
				case Agilent34980AStatusSubRegisterEnable:
					// STATus:OPERation:ENABle <register contents>
					strCommand.Format( "STAT:OPER:ENAB %ld", Val );
					break;
				default:
					return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			hr = InstrWrite( strCommand );
			break;

		case Agilent34980AStatusRegisterQuestionable:
			// 16-bit register
			Val &= 0xFFFF;
			// Only the Enable subregister is writable
			switch( SubRegister )
			{
				// STATus:QUEStionable:ENABle <register contents>
				case Agilent34980AStatusSubRegisterEnable:
					strCommand.Format( "STAT:QUES:ENAB %ld", Val );
					break;
				default:
					return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			hr = InstrWrite( strCommand );		
			break;

		case Agilent34980AStatusRegisterAlarm:
			// 16-bit register
			Val &= 0xFFFF;
			// Only the Enable subregister is writable
			switch( SubRegister )
			{
				// STATus:QUEStionable:ENABle <register contents>
				case Agilent34980AStatusSubRegisterEnable:
					strCommand.Format( "STAT:ALAR:ENAB %ld", Val );
					break;
				default:
					return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			hr = InstrWrite( strCommand );		
			break;

		case Agilent34980AStatusRegisterModule:
			// 16-bit register
			Val &= 0xFFFF;
			// Only the Enable subregister is writable
			switch( SubRegister )
			{
				// STATus:QUEStionable:ENABle <register contents>
				case Agilent34980AStatusSubRegisterEnable:
					strCommand.Format( "STAT:MOD:ENAB %ld", Val );
					break;
				default:
					return ReportInvalidValueError(_T("put_Register"), _T("SubRegister"), (long)(SubRegister));
					break;
			}
			hr = InstrWrite( strCommand );		
			break;

		default:
			return ReportInvalidValueError(_T("put_Register"), _T("Register"), (long)Register);
			break;
	}

	return hr;
}

/// <summary>
///	Serial poll the instrument status byte.
/// </summary>
/// <remarks>
///	
/// </remarks>
HRESULT Agilent34980A::IAgilent34980AStatus_get_SerialPoll(long* Val)
{
	HRESULT hr = S_OK;
	*Val = 0;

	short statusByte;
	IMessage* pIO = NULL;
	hr = ioprvGetIMessagePointer( &pIO );
	if( FAILED(hr) ) return ReportError( IDS_E_IVI_UNEXPECTED_RESPONSE );

	hr = pIO->ReadSTB(&statusByte);
	*Val = (LONG) statusByte;
	pIO->Release();
	return hr;
}

