///
/// C++ NF2 example.
/// Noise Figure 2-pass analyzer mode (Noise Source manual control).
///
#include "stdafx.h"

#include <conio.h>
#include <iostream>
#include <stdlib.h>
#include "visa.h"
#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
	ViSession rm, rsrc;
	ViStatus status;
	char address[128];
	char buff[128];
	double data[3000];
	int pass;

	// Open conection
	status = viOpenDefaultRM(&rm);
	std::cout << "Enter instrument address: "; // connect to emulator via 127.0.0.1 or localhost 
	scanf("%s", buff);
	sprintf(address, "TCPIP::%s::8888::SOCKET::NFM", buff);	
	status = viOpen(rm, address, VI_EXCLUSIVE_LOCK, 3000, &rsrc);
	if (status != VI_SUCCESS)
	{
		viStatusDesc(rm, status, buff); // Get status description
		printf("viOpen: %s\r\n", buff);
		_getch();
		return 0;
	}
	
	// Get identification data
	status = viQueryf(rsrc, "*IDN?\n", "%T", buff);
	printf("IDN: %s\r\n", buff);
	// Set timeout
	viSetAttribute(rsrc, VI_ATTR_TMO_VALUE, 10000);

	// Send "Reset" command
	status = viPrintf(rsrc, "*RST\r\n");
	// Send "Clear status" command
	status = viPrintf(rsrc, "*CLS\r\n");

	// Delete all traces
	status = viPrintf(rsrc, ":CALCulate:PARameter:DELete:ALL\n");
	// Create traces
	std::string traces[] = {"Hot", "Cold", "Noise"};
	status = viPrintf(rsrc, ":CALCulate:PARameter:DEFine \"%s\",POWHot\n", traces[0].c_str());
	status = viPrintf(rsrc, ":CALCulate:PARameter:DEFine \"%s\",POWCold\n", traces[1].c_str());
	status = viPrintf(rsrc, ":CALCulate:PARameter:DEFine \"%s\",NOISe\n", traces[2].c_str());

	// Set RBW
	status = viPrintf(rsrc, ":SENSe:BANDwidth %d\n", 1000000);
	// Set averaging
	status = viPrintf(rsrc, ":SENSe:NOISe:AVERage 5\n");
	// Set frequency range
	double start = 200, stop = 20000;
	status = viPrintf(rsrc, "SENSe:FREQuency:STARt %lfMHz;STOP %lfMHz\n", start, stop);
	// Set points count
	int points = 100;
	status = viPrintf(rsrc, "SENSe:SWEEp:POINts %d\n", points);
	// Set attenuation
	status = viPrintf(rsrc, "SENSe:IF:ATTenuation 0\n");
	status = viPrintf(rsrc, "SENSe:POWer:RF:ATTenuation 0\n");
	// Set low-temp noise source temperature (environment temp Tc is 290K by default)
	//status = viPrintf(rsrc, "SENSe:NFIGure:CORRection:MODE THOT\n");
	//status = viPrintf(rsrc, "SENSe:NFIGure:CORRection:ENR:THOT 77\n");
	// Disable continous sweeping
	status = viPrintf(rsrc, "INITiate:CONTinuous OFF\n");
	// Check errors
	status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
	printf("Error: %s\r\n", buff);

	for (pass = 0; pass < 3; pass++)
	{
		if (pass < 2) // Noise Source on/off
		{
			// Set Noise Source mode
			status = viPrintf(rsrc, "SOURce:NFIGure:NOISe:STATe %s\n", (pass == 0) ? "ON" : "OFF");
			// Trigger run
			status = viPrintf(rsrc, ":INITiate:IMMediate\n");
			// Check errors
			status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
			printf("Error: %s\r\n", buff);
			if (strcmp(buff, "+0,\"No error\"\n") != 0)
				break;
			// Wait for measurement complete
			printf("Waiting for data");
			// blocking mode
			//status = viQueryf(rsrc, "*OPC?\n", "%T", buff);
			// non-blocking mode
			status = viPrintf(rsrc, "*OPC\n");
			do
			{
				status = viQueryf(rsrc, "*ESR?\n", "%T", buff);
				printf(".");
				Sleep(100);
			}
			while (buff[0] == '0' && status == VI_SUCCESS);
		}
		else // read noise figure data
			status = VI_SUCCESS;

		if (status == VI_SUCCESS)
		{
			if (pass < 2)
				printf("Data ready\r\n");
			// Select trace
			status = viPrintf(rsrc, ":CALCulate:PARameter:SELect \"%s\"\n", traces[pass].c_str());
			// Change trace format
			status = viPrintf(rsrc, ":CALCulate:FORMat MLOGarithmic\n");
			// Set data format
			status = viPrintf(rsrc, ":FORMat REAL,64\n");
			// Check errors
			status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
			// Query data
			status = viPrintf(rsrc, ":CALCulate:DATA? FDATA\n");

			// Parse IEEE 488.2 binary block	
			ViUInt32 retCnt = 0;
			if (viRead(rsrc, (ViPBuf)buff, 2, &retCnt) < 0) // #n - number of bytes of size record
				break;
			buff[retCnt] = '\0';
			int numBytes = atoi(buff+1);
			if (buff[0]!='#' || numBytes == 0)
			{
				printf("No data in selected measurement\r\n");
				break;
			}

			if (viRead(rsrc, (ViPBuf)buff, numBytes, &retCnt) < 0) // read data length
				break;
			buff[retCnt]='\0';
			int dataSize = atoi(buff);
			if (dataSize == 0)
				break;

			if (viRead(rsrc, (ViPBuf)(data + pass * points), dataSize + 1, &retCnt) < 0)
				break;
		}
		else
			printf("Error = %d\r\n", status);
	}

	if (pass == 3)
	{
		printf("F,MHz\tPow Hot,dBm\tPow Cold,dBm\tNF,dB\r\n");
		for (int i = 0; i < points; i++)
			printf("%g\t%f\t%f\t%f\r\n", start + i*(stop-start)/(points-1), data[i], data[points + i], data[2 * points + i]);
	}

	// Wait for user action
	printf("Press any key to exit...");
	_getch();
	// Stop measurement for automatic mode
	status = viPrintf(rsrc, ":ABORt\n");
	// Close session
	status = viClose(rsrc);
	// Close resource manager
	viClose(rm);
	
	return 0;
}