///
/// C++ NF example.
/// Noise Figure analyzer mode (Noise Source modulation).
///
#include "stdafx.h"

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

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

	// 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
	status = viPrintf(rsrc, ":CALCulate:PARameter:DEFine \"Noise\",NOISe\n");
	status = viPrintf(rsrc, ":CALCulate:PARameter:DEFine \"Gain\",TRANsmit\n");

	// Load ENR
	//status = viPrintf(rsrc, ":MMEMory:LOAD:ENR \"D:\\temp\\819_50GHz.ngd\"\n");

	// Set RBW
	status = viPrintf(rsrc, ":SENSe:BANDwidth %d\n", 1000000);
	// Set averaging
	status = viPrintf(rsrc, ":SENSe:NOISe:AVERage 5\n");
	// Set NG switching time
	//status = viPrintf(rsrc, ":SENSe:NOISe:DELay 200US\n");
	// Set frequency range
	double start = 5000, stop = 9000;
	status = viPrintf(rsrc, "SENSe:FREQuency:STARt %lfMHz;STOP %lfMHz\n", start, stop);
	// Set points count
	int points = 41;
	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 Frequency Conversion parameters
	// Set IF
	/*status = viPrintf(rsrc, ":SENSe:NFIGure:MODE:DOWNconv:IF:FREQuency %lf\n", 75e6); // 75 MHz
	// Set LO type
	status = viPrintf(rsrc, ":SENSe:NFIGure:MODE:DUT:LOSCillator SWEPt\n");
	// Set LO frequency (FIXed mode only)
	status = viPrintf(rsrc, ":SENSe:NFIGure:MODE:DOWNconv:LOSCillator:FREQuency %lf\n", 1e9); // 1 GHz
	// Set LO offset
	status = viPrintf(rsrc, ":SENSe:NFIGure:MODE:DOWNconv:LOSCillator:OFFSet USB\n"); // USB: Signal Frequency > LO Frequency
	// Set enabled conversion
	status = viPrintf(rsrc, ":SENSe:NFIGure:MODE:DUT DOWNconv\n");*/

	// External Loss Compensation Before/DUT & After/DUT
	/*status = viPrintf(rsrc, ":MMEMory:LOAD:LOSS BEFore,\"e:\\DUT.s2p\"\n");
	status = viPrintf(rsrc, ":MMEMory:LOAD:LOSS AFTer,\"e:\\DUT.s2p\"\n");
	// Enable Loss Compensation Before/DUT & After/DUT
	status = viPrintf(rsrc, ":SENSe:NFIGure:CORRection:LOSS:AFTer:MODE TABLe\n");
	status = viPrintf(rsrc, ":SENSe:NFIGure:CORRection:LOSS:BEFore:MODE TABLe\n");

	// Set Trigger parameters
	/*status = viPrintf(rsrc, ":SENSe:SWEep:TRIGger:MODE SWEep\n");
	status = viPrintf(rsrc, ":TRIGger:AUXiliary:OPOLarity NEGative\n");
	status = viPrintf(rsrc, ":TRIGger:SEQuence:SOURce EXTernal\n");
	// Set Sync OUT parameters
	status = viPrintf(rsrc, ":TRIGger:AUXiliary:INTerval SWEep\n");
	status = viPrintf(rsrc, ":TRIGger:AUXiliary:DURation 125US\n");
	status = viPrintf(rsrc, ":TRIGger:AUXiliary:IPOLarity NEGative\n");
	status = viPrintf(rsrc, ":TRIGger:AUXiliary:OUTput:ENABle ON\n");*/
	
	// Check errors
	status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
	printf("Error: %s\r\n", buff);

	// Calibration
	/*printf("Calibration...\r\n");
	// Enable continous sweeping
	status = viPrintf(rsrc, "INITiate:CONTinuous ON\n");
	printf("Press any key for start calibration...\r\n");
	_getch();
	// Start calibration
	status = viPrintf(rsrc, ":SENSe:NFIGure:CALibration:INITiate\n");
	// Save calibration data to file
	status = viPrintf(rsrc, ":MMEMory:STORe:CORRection \"e:\\SelfNoise.x5mclb\"\n");
	// Load calibration data from file
	//status = viPrintf(rsrc, ":MMEMory:LOAD:CORRection \"e:\\SelfNoise.x5mclb\"\n");
	// Enable correction with calibration data
	//status = viPrintf(rsrc, ":SENSe:NFIGure:CALibration:STATe ON\n");

	// Check errors
	status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
	printf("Error: %s\r\n", buff);*/

	// 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);
	// Trigger run
	status = viPrintf(rsrc, ":INITiate:IMMediate\n");
	// Check errors
	status = viQueryf(rsrc, "SYSTem:ERRor?\n", "%T", buff);
	printf("Error: %s\r\n", buff);
	
	// Wait for measurement complete
	printf("Waiting for data...");
	status = viQueryf(rsrc, "*OPC?\n","%T", buff);
		
	if (status != VI_SUCCESS)
		printf("Error = %d\r\n", status);
	
	while (status == VI_SUCCESS)
	{
		printf("Data ready\r\n");
		// Select trace
		status = viPrintf(rsrc, ":CALCulate:PARameter:SELect \"Noise\"\n");
		// 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;

		double data[2000];
		if (viRead(rsrc, (ViPBuf)data, dataSize + 1, &retCnt) < 0)
			break;

		for (int i = 0; i < points; i++)
			printf("%g MHz\t%f dB\r\n", start + i*(stop-start)/(points-1), data[i]);

		break;
	};

	// 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;
}

