// This example demonstrates how to use
C# to setup 4 traces and to gather data using the shared memory
component
// This code should be run on the
PXI controller directly
// The example demonstrates using
helper function to check for all possible errors
// during the running of the code.
Checking for errors helps identify problems early
// Add visa32.cs to the project.
// It it is here (after installing
IO Libraries on your PC)
// C:\Program Files\IVI Foundation\VISA\Win64\agvisa\include\agvisa32.cs
using System;
using System.Text;
using System.IO.MemoryMappedFiles;
class SharedMemory
{
// Variables to store the VISA session
numbers
static int
g_defaultSession = -1;
static int
g_session = -1;
static void
Main(string[]
args)
{
try
{
// Find the VISA address from the SCPI
parser console on your VNA
// System->System Setup->Remote
Interface... Show SCPI parser Console -> Status
// TODO: CHANGE THIS VISA_ADDRESS to point
to your VNA
string VISA_ADDRESS
= "TCPIP0::localhost::hislip0,4880::INSTR";
int timeout
= 1000;
CheckViStatus(visa32.viOpenDefaultRM(out
g_defaultSession));
CheckViStatus(visa32.viOpen(g_defaultSession,
VISA_ADDRESS, 0, timeout,
out g_session));
CheckViStatus(visa32.viSetAttribute(g_session,
visa32.VI_ATTR_TMO_VALUE,
timeout));
int s
= g_session; //
s is a alias for session
WriteString("SYST:FPR");
WriteString("DISP:WIND:STAT
1");
// initialize memory mapped structures
in VNA
WriteString("SYST:DATA:MEM:INIT\n");
// Create 4 SParameters
string[] parameters
= new string[]
{ "S11", "S21", "S12",
"S22" };
int[] offsets_for_complex_data
= new int[parameters.Length];
int[] offsets_for_formatted_data
= new int[parameters.Length];
for (int
i = 0; i
< parameters.Length; i++)
{
// Create a new parameter
WriteString($"CALC1:MEAS{i + 1}:DEF
'{parameters[i]}'");
WriteString($"DISP:MEAS{i+1}:FEED
1\n");
// Configure a new section of the memory
map to monitor the complex data of this parameter
WriteString("SYST:DATA:MEM:ADD
'1:" + (i + 1).ToString() + ":SDATA:201'");
// add parameter to memory mapped
offsets_for_complex_data[i] = int.Parse(Query("SYST:DATA:MEM:OFFSet?"));
// Configure a new section of the memory
map to monitor the formatted data of this parameter
WriteString("SYST:DATA:MEM:ADD
'1:" + (i + 1).ToString() + ":FDATA:201'");
// add parameter to memory mapped
offsets_for_formatted_data[i] = int.Parse(Query("SYST:DATA:MEM:OFFSet?"));
}
// Tell the VNA to allocate the memory
map. Name it "VNA_MemoryMap"
WriteString("SYST:DATA:MEM:COMM
'VNA_MemoryMap'");
// Query the size of the memory map
int size
= int.Parse(Query("SYST:DATA:MEM:SIZE?"));
// Create the memory map in C#. This requires
.NET 4.5 framework
MemoryMappedFile mappedFile
= MemoryMappedFile.CreateOrOpen("VNA_MemoryMap",
size);
MemoryMappedViewAccessor mappedFileView = mappedFile.CreateViewAccessor();
// Trigger a single sweep, and wait for
it to complete
WriteString("SENS:SWE:MODE
SING");
Query("*OPC?");
// Allocate buffers to hold the output
data
float[][] complexData
= new float[parameters.Length][];
for (int
i = 0; i
< complexData.Length; i++)
{
complexData[i]
= new float[402];
}
float[][] formattedData
= new float[parameters.Length][];
for (int
i = 0; i
< formattedData.Length; i++)
{
formattedData[i]
= new float[201];
}
// Copy the data from the memory map into
the output buffers
// These copy the data from the in-process
memory map.
// This runs very fast - and is just a
"memcpy" under the hood
for (int
i = 0; i
< parameters.Length; i++)
{
ReadBytes(mappedFileView,
offsets_for_complex_data[i], 402, complexData[i]);
ReadBytes(mappedFileView,
offsets_for_formatted_data[i], 201, formattedData[i]);
}
// Output some data to show that it worked
Console.WriteLine(complexData[0][0].ToString());
// Output first point of S11 in
complex
Console.WriteLine(formattedData[3][200].ToString()); //
Output last point of S22 as formatted
}
catch (Exception
ex)
{
Console.WriteLine(ex.Message);
}
// Close the handles - even if there was
an error
if (g_session
!= -1)
visa32.viClose(g_session);
if (g_defaultSession
!= -1)
visa32.viClose(g_defaultSession);
}
static public
unsafe void
ReadBytes(MemoryMappedViewAccessor
mappedFileView,
int offset,
int num,
float[] arr)
{
// This is equivalent to:
// //m_mappedFileView.ReadArray<float>(m_sharedMemoryOffsets[i-1],
complexArray, 0, points*2);
// But, using this "unsafe"
code is 30 times faster. 100usec versus 3ms
byte* ptr
= (byte*)0;
mappedFileView.SafeMemoryMappedViewHandle.AcquirePointer(ref
ptr);
System.Runtime.InteropServices.Marshal.Copy(IntPtr.Add(new
IntPtr(ptr),
offset), arr,
0, num);
mappedFileView.SafeMemoryMappedViewHandle.ReleasePointer();
}
static void
WriteString(string
command)
{
command += "\n";
CheckViStatus(visa32.viPrintf(g_session,command));
CheckForErrors();
}
static string
Query(string
query)
{
query += "\n";
CheckViStatus(visa32.viPrintf(g_session,query));
StringBuilder errorMessage
= new StringBuilder();
CheckViStatus(visa32.viScanf(g_session,
"%t", errorMessage));
return errorMessage.ToString();
}
// Helper function to check for any error
with a VISA call
static void
CheckViStatus(int
viStatus)
{
if (viStatus
< 0) // If the viStatus is less
than 0, then it indicates an error
{
// Convert the error number to a string
StringBuilder errorMessage
= new StringBuilder();
visa32.viStatusDesc(g_session,
viStatus, errorMessage);
// Throw an exception with the string
throw new
Exception(errorMessage.ToString());
}
}
// Helper function to check for logical
SCPI errors
static void
CheckForErrors()
{
// Next check if there was a SCPI error
CheckViStatus(visa32.viPrintf(g_session,
"SYST:ERR:COUN?\n"));
int errorCount;
CheckViStatus(visa32.viScanf(g_session,
"%d", out
errorCount));
if (errorCount
== 0)
return; //
no errors
// There is an error, let's convert it
to a string
StringBuilder allErrors
= new StringBuilder();
for (int
i = 0; i
< errorCount; i++)
{
CheckViStatus(visa32.viPrintf(g_session,
"SYST:ERR?\n"));
StringBuilder errorMessage
= new StringBuilder();
CheckViStatus(visa32.viScanf(g_session,
"%t", errorMessage));
allErrors.Append(errorMessage);
}
throw new
Exception(allErrors.ToString());
}
}
|