///
/// C++ SA example.
/// Spectrum analyzer mode.
///
#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::SAM", 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 \"Power\",POWer\n");

	// Set RBW
	status = viPrintf(rsrc, ":SENSe:BANDwidth %d\n", 10000);
	// Set frequency range values
	double center = 1000, span = 10;
	status = viPrintf(rsrc, "SENSe:FREQuency:CENTer %lfMHz;SPAN %lfMHz\n", center, span);
	// Set points count
	int points = 101;
	status = viPrintf(rsrc, "SENSe:SWEEp:POINts %d\n", points);
	// Set Reference Level
	double rlev = 0;
	status = viPrintf(rsrc, "SENSe:POWer:RLEVel %lf\n", rlev);
	// Set Input Mode
	//status = viPrintf(rsrc, "INPut:COUPling AC\n");
	// Set VBW
	status = viPrintf(rsrc, ":SENSe:BANDwidth:VIDeo 3000\n");
	// Set Detector
	status = viPrintf(rsrc, ":SENSe:DETector:FUNCtion NORMal\n");
	// Enable Noise Source
	//status = viPrintf(rsrc, "SOURce:NFIGure:NOISe: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 \"Power\"\n");
		// Change trace format
		status = viPrintf(rsrc, ":CALCulate:FORMat dbm\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;

		double step = (points > 1) ? span / (points - 1) : 0;
		for (int i = 0; i < points; i++)
			printf("%g MHz\t%f dBm\t\r\n", center - span / 2 + i * step, 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;
}