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



/// <summary>
/// Downloads 16-bit signed integer values between -32768 and +32767 into volatile
///   memory on the 34951A Isolated DAC Module in the specified slot.
/// </summary>
/// <remarks>
/// The data in the DataArray is a DAC code representation of a number between -1.0
/// and +1.0, where 32767 = 1.0 and -32768 = -1.0.  The trace is created, given
/// a name, and saved into memory on the module indicated by SlotNumber parameter
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="Name">
///	Name of the trace consisting of up to 12 characters. The first character must
///  be a letter (A-Z), but the remaining 11 characters can be letters, numbers
/// (0-9), or an underscore ( _ ). Blank spaces are not allowed
/// </param>
/// <param name="Points">
///	The number of the values in DataArray.
/// </param>
/// <param name="DataArray">
///	Peak-to-peak trace values between -32768 and +32767.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_CreateCustomInteger(long SlotNumber, BSTR Name, long Points, SAFEARRAY** DataArray)
{
	HRESULT hr = S_OK;

	long lLBound, lUBound, len;
	RETURN_IF_FAIL( ::SafeArrayGetLBound(*DataArray, 1, &lLBound) );
	RETURN_IF_FAIL( ::SafeArrayGetUBound(*DataArray, 1, &lUBound) );
	len = lUBound - lLBound + 1;

	double *pData = new double	[len];
	int *pDataInt = new int[len];
	sptrarray sp(pData);
	sptrarray spi(pDataInt);

	try
	{
		long lActualLen;
		CSafeArray<int>::Write( *DataArray, pDataInt, len, &lActualLen );
	}catch(...)
	{
		return ReportError( IDS_E_IVI_INVALID_VALUE );
	}
	for( int i=0; i<len; i++ )
		pData[i] = ((double)(pDataInt[i])) / 32767;

	hr = _CreateCustomFloat( SlotNumber, Name, Points, pData, len );
	return hr;
}

HRESULT Agilent34951A::_CreateCustomFloat(long slotNumber, BSTR name, long points, double* pData, long length )
{
	HRESULT hr = S_OK;

	CString sCmd;
	sCmd.Format(":TRAC %d, %s ", slotNumber, LPCTSTR(COLE2T(name)) );
	char buf[100];
	try
	{ 
		for( int i=0; i<points; i++ )
		{
			(sCmd += ", ") += _gcvt( *(pData+i), 20, buf );
		}
	}
	catch(...)
	{
		return ReportError( IDS_E_IVI_INVALID_VALUE );
	}

	hr = InstrPrintf( sCmd );
	return hr;
}
/// <summary>
/// Downloads 32-bit floating-point values between -1 and +1 into volatile memory
/// on the 34951A Isolated DAC Module in the specified slot.
/// </summary>
/// <remarks>
/// The data in the DataArray is a DAC code representation of a number between -1.0
/// and +1.0, where 32767 = 1.0 and -32768 = -1.0.  The trace is created, given
/// a name, and saved into memory on the module indicated by SlotNumber parameter
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="Name">
///	Name of the trace consisting of up to 12 characters. The first character must
///  be a letter (A-Z), but the remaining 11 characters can be letters, numbers
/// (0-9), or an underscore ( _ ). Blank spaces are not allowed.
/// </param>
/// <param name="NumPoints">
///	The number of the values in DataArray.
/// </param>
/// <param name="DataArray">
///	Peak-to-peak trace point values between -1.0 and +1.0.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_CreateCustomFloat(long SlotNumber, BSTR Name, long NumPoints, SAFEARRAY** DataArray)
{
	HRESULT hr = S_OK;
	long lLBound, lUBound, len;
	RETURN_IF_FAIL( ::SafeArrayGetLBound(*DataArray, 1, &lLBound) );
	RETURN_IF_FAIL( ::SafeArrayGetUBound(*DataArray, 1, &lUBound) );
	len = lUBound - lLBound + 1;

	double *pData = new double[len];
	sptrarray sp(pData);
	try
	{
		long lActualLen;
		CSafeArray<double>::Write( *DataArray, pData, len, &lActualLen );
	}
	catch(...)
	{
		return ReportError( IDS_E_IVI_INVALID_VALUE );
	}
	hr = _CreateCustomFloat( SlotNumber, Name, NumPoints, pData, len );
	return hr;
}


/// <summary>
/// Generates trace data based on several standard shapes on the 34951A Isolated DAC Module in the specified slot. 
/// </summary>
/// <remarks>
/// The data generated is between -1 and +1 and you can download between 8 and 512,000 points.
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="Name">
///	Name of the trace consisting of up to 12 characters. The first character must be a letter (A-Z), but the remaining 11 characters can be letters, numbers (0-9), or an underscore ( _ ). Blank spaces are not allowed.
/// </param>
/// <param name="Points">
///	The length of the trace between 8 and 512,000 points.
/// </param>
/// <param name="Type">
///	Trace Waveform.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_CreateStandard(long SlotNumber, BSTR Name, long Points, Agilent34951ATraceWaveformEnum Type)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}


/// <summary>
/// Deletes a trace from volatile memory on the 34951A Isolated DAC Module in the
/// specified slot.
/// </summary>
/// <remarks>
/// Deleting a trace also frees up space in memory previously allocated for the
/// trace.  A running trace may not be deleted until it is stopped.  To stop a running
/// trace, set the IAgilent34951AOutput.State Property to OFF, and then set the
/// IAgilent34951ASource.OperationMode Property to False (disabled).
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="TraceName">
///	A previously defined trace name consisting of up to 12 characters.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_Delete(long SlotNumber, BSTR TraceName)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}


/// <summary>
/// Deletes all traces from memory on the 34951A DAC Module in the specified slot.
/// </summary>
/// <remarks>
/// Deleting a trace also frees up space in memory previously allocated for the
/// trace.  A running trace may not be deleted until it is stopped.  To stop a running
/// trace, set the IAgilent34951AOutput.State Property to OFF, and then set the
/// IAgilent34951ASource.OperationMode Property to False (disabled).
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_DeleteAll(long SlotNumber)
{
	HRESULT hr = S_OK;

	hr = InstrPrintCommand();

	return hr;
}

/// <summary>
/// Creates a trace from data in the specified file.  The file is a text file, consisting
/// of numbers between -1.0 and +1.0, each number is on its own line (i.e. a newline
/// character appears after each numeric entry, except the last one).  The file
/// contains only the data itself.
/// </summary>
/// <remarks>
/// 
/// </remarks>
/// <returns>
///	
/// </returns>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="Name">
///	Name of the trace consisting of up to 12 characters. The first character must
/// be a letter (A-Z), but the remaining 11 characters can be letters, numbers (0-9),
/// or an underscore ( _ ). Blank spaces are not allowed.
/// </param>
/// <param name="SourceFile">
///	Fully qualified file name.  NOTE:  If backslashes are used, you must use two
/// of them, otherwise, forward slashes may also be used.  Example:  C:\\TEMP\\DataFile.txt
/// or C:/TEMP/DataFile.txt.
/// </param>

HRESULT Agilent34951A::IAgilent34951ATrace_CreateCustomFromFile(long SlotNumber, BSTR Name, BSTR SourceFile)
{
	HRESULT hr = S_OK;

	//prepare params for CreateCustomFloat and call it
	long numPoints = 0;
	CFileReader fr( SourceFile );
	if( ! fr.bDataOK )
		return ReportInvalidValueError( _T("IAgilent34951ATrace_CreateCustomFromFile"),_T("SourceFile"), LPCTSTR(COLE2T(SourceFile)) );
	double *data = ::new double[ fr.lSize/3 ]; // assuming a number in the file will take at least 3 chars
	long count = strtok2cont( fr.pData, fr.pData+fr.lSize, double_inserter( data ), (char*)"\r\n, " );

	hr = _CreateCustomFloat( SlotNumber, Name, count, data, 0 );
	::delete []data;
	return hr;
}

/// <summary>
/// Returns the number of points used by the trace waveform on the 34951A Isolated DAC Module in the specified slot.
/// </summary>
/// <remarks>
///	You can store up to 512,000 trace points per 34951A module.
/// </remarks>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
/// <param name="Name">
///	A previously defined trace name consisting of up to 12 characters.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_get_Points(long SlotNumber, BSTR Name, long* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(Val);

	return hr;
}



/// <summary>
/// Returns the largest contiguous block of available volatile memory on the 34951A Isolated DAC Module in the specified slot
/// </summary>
/// <remarks>
///	The value returned is the number of trace points available for the specified slot.
/// </remarks>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_get_MemoryFree(long SlotNumber, long* Val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand( Val );

	return hr;
}




/// <summary>
///	Returns a list of trace names currently downloaded to volatile memory on the
/// 34951A Isolated DAC Module in the specified slot.
/// </summary>
/// <remarks>
///	
/// </remarks>
/// <param name="SlotNumber">
///	The number of the slot (1 to 8) where 34951A Isolated DAC Module is located.
/// </param>
HRESULT Agilent34951A::IAgilent34951ATrace_get_Catalog(long SlotNumber, BSTR* val)
{
	HRESULT hr = S_OK;

	hr = InstrQueryCommand(val);

	return hr;
}
