////////////////////////////////////////////////////////////////////////////
// AO "NPF Micran" 26.04.2021
// This is an example for P2M with SCPI commands
// C# example 2.
// Frequency sweep with fixed power
////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using MiVisa;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			StringBuilder buff = new StringBuilder(1000);
			ViStatus status;
			ViSession rm, rsrc;
			string addr;
			
			status = Visa.GetDefaultRM(out rm);

			System.Console.Out.WriteLine("Enter device address:");   
			addr = System.Console.In.ReadLine();

			// Open conection through MICS class
			status = Visa.Open(rm, "TCPIP::" + addr + "::8888::SOCKET::SNM", ViAccessMode.VI_EXCLUSIVE_LOCK, 5000, out rsrc);
			if (status != ViStatus.VI_SUCCESS)
			{
				Visa.StatusDesc(rm, status, buff); // Get status description
				System.Console.Out.WriteLine("viOpen: " + buff);
				System.Console.ReadKey();
				return;
			}
			// Set operation timeout (ms)
			Visa.SetAttribute(rsrc, ViAttr.VI_ATTR_TMO_VALUE, 3000);
			// Send commands
			// Send "Reset" command
			status = Visa.Printf(rsrc, "*RST\n");
			// Send "Clear status" command
			status = Visa.Printf(rsrc, "*CLS\n");

			// Send "IDN" command
			status = Visa.Printf(rsrc, "*IDN?\n");
			status = Visa.Scanf(rsrc, "%T", buff);
			System.Console.Out.WriteLine(buff);

			// Set frequency sweep mode
			status = Visa.Printf(rsrc, "SENSe:FREQuency:MODE SWEep\n");

			// Set frequency range values
			double start = 10, stop = 20000;
			status = Visa.Printf(rsrc, "SENSe:FREQuency:STARt %lfMHz;STOP %lfMHz\n", __arglist(start, stop));
			status = Visa.Printf(rsrc, "SENSe:FREQuency:STARt?\n");
			status = Visa.Scanf(rsrc, "%T", buff);
			System.Console.Out.WriteLine(buff);

			// Set points count
			int points = 501;
			status = Visa.Printf(rsrc, "SENSe:SWEEp:POINts %d\n", points);
			status = Visa.Printf(rsrc, "SENSe:SWEEp:POINts?\n");
			status = Visa.Scanf(rsrc, "%T", buff);
			System.Console.Out.WriteLine(buff);

			// Set fixed power mode
			status = Visa.Printf(rsrc, "SOURce:POWer:MODE FIXed\n");

			// Set power level value
			status = Visa.Printf(rsrc, "SOURce:POWer:LEVel -5DBM\n");

			// Set power out on
			status = Visa.Printf(rsrc, "OUTPut:STATe ON\n");
			
			// Set only one sweep
			status = Visa.Printf(rsrc, "INITiate:CONTinuous OFF\n");

			// Get input list
			status = Visa.Printf(rsrc, "CALCulate:PARameter:CATalog?\n");
			status = Visa.Scanf(rsrc, "%T", buff);
			System.Console.Out.WriteLine(buff);

			// Get error count
			status = Visa.Printf(rsrc, "SYSTem:ERRor:Count?\n");
			status = Visa.Scanf(rsrc, "%T", buff);
			System.Console.Out.WriteLine(buff);
			
			// Get error
			StringBuilder sb = new StringBuilder(1000);
			status = Visa.Queryf(rsrc, "SYSTem:ERRor?\n", "%T", __arglist(sb));
			System.Console.Out.WriteLine(sb.ToString());

			// Trigger RUN
			status = Visa.Printf(rsrc, "INITiate:IMMediate\n");
			
			Visa.Printf(rsrc, "*OPC?\n");
			do
			{
				// Wait for measurement complete
				status = Visa.Scanf(rsrc, "%T", buff);
			}
			while (status != ViStatus.VI_SUCCESS);

			System.Console.Out.WriteLine("Data ready");
			
			// Read data
			if (status == ViStatus.VI_SUCCESS)
			{
				// Select input
				status = Visa.Printf(rsrc, "CALCulate:PARameter:SELect A\n");
				// Set data format
				status = Visa.Printf(rsrc, "FORMat REAL,64\n");
				status = Visa.Printf(rsrc, "CALCulate:DATA?\n");

				byte[] bytes = new byte[2];
				uint retCnt = 0;
				if (Visa.Read(rsrc, bytes, 2, out retCnt) < 0) // #n - number of bytes of size record
					return;
				uint numBytes = Convert.ToUInt32(Encoding.ASCII.GetString(bytes, 1, 1));
				if (numBytes == 0)
					return;
				bytes = new byte[numBytes];
				if (Visa.Read(rsrc, bytes, numBytes, out retCnt) < 0) // read data length
					return;
				uint dataSize = Convert.ToUInt32(Encoding.ASCII.GetString(bytes, 0, (int)numBytes));
				if (dataSize == 0)
					return;
				bytes = new byte[dataSize + 1];
				if (Visa.Read(rsrc, bytes, dataSize + 1, out retCnt) < 0)
					return;
				for (int i = 0; i < points; i++)
				{
					try
					{
						double val = BitConverter.ToDouble(bytes, 8 * i);
						Console.WriteLine(start + i * (stop - start) / (points - 1) + " MHz\tPow: " + Math.Round(val, 3) + "\t мкВ"); 
					}
					catch
					{
						System.Console.Out.WriteLine("Incorrect data");
					}
				}
			}
			
			// Set power out off
			status = Visa.Printf(rsrc, "OUTPut:STATe OFF\n");
			
			// Close session
			status = Visa.Close(rsrc);

			// Close resource manager
			Visa.Close(rm);

			// Wait for user action
			System.Console.Out.WriteLine("Press any key to exit...");
			System.Console.ReadKey();
		}
	}
}