// CycleTime.cpp -- Cycle time measurement. SCPI automation is used trough VISA library and TCP/IP protocol HiSLIP or Socket. 
//
// VISA Header: visa.h (must be included)
// VISA Library: visa32.lib (must be linked with)
// check "how to link visa library.txt" for how to link

#include "visa.h"
#include<iostream>
#include<windows.h>
#include<cstdint>
#include<conio.h>
using namespace std;
   
//---------------------------------------------------------------------------
// Prototypes
void StartTimeMeasurement(_LARGE_INTEGER& startTime);
double GetElapsedTime(const _LARGE_INTEGER& startTime);
void GetSParameter(ViSession instr, double data[], int arraySize);
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	ViSession defaultRM, instr;             // Communication channels
	const int NOP = 201;                   // Number of measurement points
	ViUInt32 retCount = NOP * 2;                      // Return count for I/O 
	double dataS11[NOP * 2];                  // Measurement data array
	double dataS21[NOP * 2];                  // Measurement data array
	double dataS12[NOP * 2];                  // Measurement data array
	double dataS22[NOP * 2];                  // Measurement data array
	_LARGE_INTEGER startTime;               // Time measurement

	if (viOpenDefaultRM(&defaultRM) == VI_SUCCESS)
	{
		if (viOpen(defaultRM, "TCPIP0::127.0.0.1::5025::SOCKET", VI_NULL, VI_NULL, &instr) == VI_SUCCESS)
		{
			// Set timeout 
			viSetAttribute(instr, VI_ATTR_TMO_VALUE, 5000);
			// Set termination character for Socket (for HiSLIP has no effect)
			viSetAttribute(instr, VI_ATTR_TERMCHAR_EN, VI_TRUE);
			// Set up the Analyzer
			viPrintf(instr, "SENS:SWEEP:POIN %d\n", NOP);
			viPrintf(instr, "SENS:BAND %f\n", 100e3);
			viPrintf(instr, "SENS:FREQ:STAR %f\n", 10.0e6);
			viPrintf(instr, "SENS:FREQ:STOP %f\n", 9.0e9);
			viPrintf(instr, "CALC:PAR:COUN %d\n", 4);
			viPrintf(instr, "CALC:PAR1:DEF S11\n");
			viPrintf(instr, "CALC:PAR2:DEF S21\n");
			viPrintf(instr, "CALC:PAR3:DEF S12\n");
			viPrintf(instr, "CALC:PAR4:DEF S22\n");
			viPrintf(instr, "TRIG:SOUR BUS\n");
			//viPrintf(instr, "DISP:ENAB OFF\n");          // Turn off display update
			// Wait for setup completes
			viQueryf(instr, "*OPC?\n", "%*t");

			printf("Measurement Cycle. Press Enter to Exit\n\n");
			for (int i = 0; !_kbhit(); ++i)
			{
				StartTimeMeasurement(startTime);
				// Trigger measurement and wait for completion
				viQueryf(instr, "TRIG:SING;*OPC?\n", "%*t");
				// Read out measurement data
				viQueryf(instr, "CALC:TRAC1:DATA:FDAT?\n", "%,#lf", &retCount, dataS11);
				viQueryf(instr, "CALC:TRAC2:DATA:FDAT?\n", "%,#lf", &retCount, dataS21);
				viQueryf(instr, "CALC:TRAC3:DATA:FDAT?\n", "%,#lf", &retCount, dataS12);
				viQueryf(instr, "CALC:TRAC4:DATA:FDAT?\n", "%,#lf", &retCount, dataS22);

				// Display cycle time
				printf("Cycle time: %lf ms  \r", GetElapsedTime(startTime) * 1000.);
			}

			// uncomment to check if the data collected is correct
			//for (int i = 0; i < NOP * 2; i++) {
			//	printf("%lf,", dataS11[i]);
			//}

			viPrintf(instr, "TRIG:SOUR INT\n");
			viPrintf(instr, "DISP:ENAB ON\n");
			viClose(instr);
			getchar(); // hold the console window open
		}
		else printf("Cannot open VISA address: %s\n", argv[1]);
		viClose(defaultRM);
		getchar();
	}
	else printf("Cannot initialize VISA\n");
	getchar();

	return 0;
}

//---------------------------------------------------------------------------
void StartTimeMeasurement(_LARGE_INTEGER& startTime)
{
	QueryPerformanceCounter(&startTime);
}
//---------------------------------------------------------------------------
double GetElapsedTime(const _LARGE_INTEGER& startTime)
{
	_LARGE_INTEGER stopTime;
	_LARGE_INTEGER frequency;
	QueryPerformanceCounter(&stopTime);
	QueryPerformanceFrequency(&frequency);
	return double(stopTime.QuadPart - startTime.QuadPart) / frequency.QuadPart;
}
//---------------------------------------------------------------------------
void GetSParameter(ViSession instr, double data[], int arraySize)
{
	ViUInt32 retCount;
	retCount = arraySize; // Input: buffer size in doubles / Output: actually transferred count of doubles       
	viQueryf(instr, "CALC:DATA:FDAT?\n", "%,#lf", &retCount, data);

}
//---------------------------------------------------------------------------
