// DigMemRead.cpp : Example of using the 34950A to read digital data into memory

// NOTE: Is .cpp file, but really uses ANSI C syntax
//
// """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
//  © Agilent Technologies Inc. 2005, 2006
//  All rights reserved.
//
// You have a royalty-free right to use, modify, reproduce and distribute
// the Sample Application Files (and/or any modified version) in any way
// you find useful, provided that you agree that Agilent Technologies has no
// warranty, obligations or liability for any Sample Application Files.
//
// Agilent Technologies provides programming examples for illustration only,
// This sample program assumes that you are familiar with the programming
// language being demonstrated and the tools used to create and debug
// procedures. Agilent Technologies support engineers can help explain the
// functionality of Agilent Technologies software components and associated
// commands, but they will not modify these samples to provide added
// functionality or construct procedures to meet your specific needs.
// """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
//
// This program demonstrates how to receive digital data on the 34950A module
// and place it into memory (creating a Trace).  The data is received by this
// card and is assumed to be transmitted from some other device (not shown).
//

#include "stdafx.h"
#include "ag34980a.h"
// NOTE: The above include (ag34980A.h) needs some IVI includes.  The path to these
// is often something like "C:\Program Files\IVI\Include".  You need to add this to your includes path at
// either the project level or the system level.  For project level, select Tools\Options, then click
// on "Projects" file tab, select "VC++ Directories".  This brings up a dialog box.  In the upper
// right of this dialog, there is a "Show Directories for" drop down -- select Include files. Then 
// input the include path desired in the window beneath.  You may also need to add an include path
// for Visa.h (if you are using Agilent's Visa, this is often in C:\Program Files\Visa\winnt\include).
// If you are using NI's Visa, then try looking for the include directory somewhere beneath "C:\vxipnp"

ViSession vi;  // needs to be global so can print errors out

void printErrs(ViStatus s)
{
	char errMssg[300];
	ViInt32 errCode = -1;
	ViStatus s2;

	s2 = ag34980a_GetError(vi, &errCode, (ViInt32)300, errMssg);
	printf("Got Visa error: %ld, %s\n", errCode, errMssg);
	if (errCode = -1074135039)  // instr has errors in its queue
	{
		// print out the instr specific errors
		while ((s2 >= 0) && (errCode != 0))
		{
			s2 = ag34980a_error_query(vi, &errCode, errMssg);
			if ( (s2 > -1) && (errCode != 0) )
				printf("Instr reported err: %ld, %s\n", errCode, errMssg);
		}
	}
}
   
#define	CHECK(func)	\
do {\
    ViStatus _s = (func);\
    if (_s < 0)\
    {\
	printf("Error calling function: %s\n", #func);\
	printErrs(_s);\
    }\
} while (0)
 // Uncomment and add the following two lines before the "while" above if you wish to exit when
 // you detect an error.
 //	_s = ag34980a_close(vi);\
 //   exit(0);



int main(int argc, char* argv[])
{
    // This example assumes a 34950A is present in slot 3 

	ViStatus viStatus;
	ViBoolean myBool;
	ViInt32 numPoints;
	ViInt32 actualLen;

	// declare array to hold data
	ViInt32 dataArray[4000];  // more than enough room
	
	//Open a session to the mainframe using the IVI-C host driver, Reset the instrument
	// If third parameter VI_TRUE, then *RST is done
	viStatus = ag34980a_InitWithOptions( "TCPIP0::156.140.92.161::inst0::INSTR", VI_FALSE, VI_TRUE,"QueryInstrStatus=true", &vi );
	
	if (viStatus < 0)
	{
		fprintf(stderr,"Failed to open the instrument.");
		exit(0);
	}

	// set timeout to 5 seconds
    CHECK( ag34980a_SetAttributeViInt32(vi, "", AG34980A_ATTR_TIMEOUT_MILLISECONDS,5000) );

//	Configure receiver for Input, width = byte, threshold 2.5
	CHECK(ag34980a_ConfigureInput(vi,"1101",AG34980A_VAL_CHANNEL_WIDTH_BYTE, 2.5) );

//  Set up the Sync strobe to be external
//  NOTE:  This step needs to be done before memory is "enabled" by ConfigureInputMemory
	CHECK(ag34980a_SetAttributeViInt32(vi,"1101",AG34980A_ATTR_HANDSHAKE_SYNC_STROBE,AG34980A_VAL_HANDSHAKE_STROBE_SOURCE_EXTERNAL) );

//	Set up the desired pattern comparison action and the sample count
 	CHECK(ag34980a_ConfigureInputMemory(vi,"1101",AG34980A_VAL_ACTION_CONTINUE,3000) );

//	Set up handshaking, synchronous, threshold 2.4, output level 5.0
	CHECK(ag34980a_ConfigureHandshake(vi,"1101",AG34980A_VAL_HANDSHAKE_MODE_SYNCHRONOUS,2.5,5.0) ); 
    CHECK(ag34980a_SetPolarity(vi,"1101",AG34980A_VAL_HANDSHAKE_LINE_IDH2,AG34980A_VAL_POLARITY_INVERTED) );

	// NOTE: Polarity above may need to be "Inverted" if you are pacing the sender
	// with the same clock the receiver is using -- that way, the rising edge can 
	// cause an output on the sender, and the falling edge can start the "read";
	// the time between edges allows the data to become "stable" before the read. 
	// Unpredictable results occur if you attempt to use the same edge of a single clock
	// source to both pace the "send" and to trigger the "read".

//	Set up receiver, rate is 500K, external source for the strobe
	CHECK(ag34980a_SetAttributeViReal64(vi,"1101",AG34980A_ATTR_HANDSHAKE_RATE,500000.0) ); 
//	Clear Memory		
	CHECK(ag34980a_ClearInputMemory(vi,"1101") );

//	Now you must set up the device that is sending the digital patterns (not shown here)

//	Start the receiver first, then start the sender
	CHECK(ag34980a_StartInput(vi,"1101") );

//	Start the sender, he will pace the transfer

//	Check the status and make sure we are running
	CHECK(ag34980a_GetAttributeViBoolean(vi,"1101",AG34980A_ATTR_INPUT_STATUS,&myBool) );

	if (!myBool)
		printf("Expected status to be true, was false (memory not started)\n");

	// May need to delay here while transfer is happening -- or put breakpoint on next statement
	
//	After transfer complete, stop the receiver 
	CHECK(ag34980a_StopInput(vi,"1101") );

//	Now read what was written into memory
//	NOTE: You MUST Disable memory on the receiver before reading the contents
	CHECK(ag34980a_SetAttributeViBoolean(vi,"1101",AG34980A_ATTR_ENABLE_INPUT_MEMORY, VI_FALSE) );

//  See how much data was sent
	CHECK(ag34980a_GetAttributeViInt32(vi,"1101",AG34980A_ATTR_DATA_POINTS,&numPoints) );

	if (numPoints > 0)
	{
		CHECK(ag34980a_ReadAllData(vi,"1101",4000,dataArray,&actualLen) );
		printf("\n %d points transferred.", numPoints);
	}
	else
		printf("No data was transmitted.\n");
	
	//  Exit and close session
	viStatus = ag34980a_close(vi);

	printf("\n Done -- press enter to exit program.");
	getchar();

	return 0;
}

