This section examines the C++ code algorithm for creating and downloading I/Q waveform data by breaking the programming example into functional parts and explaining the code in generic terms. This is done to help you understand the code algorithm in creating and downloading the I and Q data, so you can leverage the concept into your programming environment.
You can use various programming environments to create Arb waveform data. Generally there are two types:
Simulation software such as MATLAB.
Advanced programming languages including, C++, VB, VEE, MS Visual Studio.Net, Labview, and so forth.
No matter which programming environment you use to create the waveform data, make sure that the data conforms to the data requirements shown in Waveform Data Requirements. To learn more about I/Q data for the PXB, see Understanding Binary Formatted Waveform Data.
There are three steps in the process of creating an I/Q waveform:
Create the I and Q data.
Save the I and Q data to a text file for review.
Interleave the I and Q data to make an I/Q file, and swap the byte order for little endian platforms.
For information on downloading I/Q waveform data to a PXB, refer to Downloading and Extracting Waveform Data.
The following lines of code create scaled I and Q data for a sine wave. The I data consists of one period of a sine wave and the Q data consists of one period of a cosine wave.
Line |
Code – Create I and Q data
|
1 |
const int NUMSAMPLES= 512; |
2 |
main(int argc, char* argv[]); |
3 |
{ |
4 |
short idata [NUMSAMPLES]; |
5 |
short qdata [NUMSAMPLES]; |
6 |
int numsamples = NUMSAMPLES; |
7 |
for(int index=0; index<numsamples; index++); |
8 |
{ |
9 |
idata[index]=32768 * sin((2*3.14*index)/numsamples); |
10 |
qdata[index]=32768 * cos((2*3.14*index)/numsamples); |
11 |
} |
Line |
Code Description Create I and Q data– |
||
1 |
Define the number of waveform points. Note that the maximum number of waveform points that you can set is based on the amount of available memory in the PXB. |
||
2 |
Define the main function in C++. |
||
4 |
Create an array to hold the generated I values. The array length equals the number of the waveform points. Note that we define the array as type short, which represents a 16-bit signed integer in most C++ compilers. |
||
5 |
Create an array to hold the generated Q values (signed 16-bit integers). |
||
6 |
Define and set a temporary variable, which is used to calculate the I and Q values. |
||
7-11 |
Create a loop to do the following:
|
The following lines of code export the I and Q data to a text file for validation. After exporting the data, open the file using Microsoft Excel or a similar spreadsheet program, and verify that the I and Q data are correct.
Line |
Code – Saving the I/Q Data to a Text File
|
12 |
char *ofile = "c:\\temp\\iq.txt"; |
13 |
FILE *outfile = fopen(ofile, "w"); |
14 |
if (outfile==NULL) perror ("Error opening file to write"); |
15 |
for(index=0; index<numsamples; index++) |
16 |
{ |
17 |
fprintf(outfile, "%d, %d\n", idata[index], qdata[index]); |
18 |
} |
19 |
fclose(outfile); |
Line |
Code – Description Saving the I/Q Data to a Text File |
12 |
Set the absolute path of a text file to a character variable. In this example, iq.txt is the file name and *ofile is the variable name. For the file path, some operating systems may not use the drive prefix (’r;c:’ in this example), or may require only a single forward slash (/), or both ("/temp/iq.txt") |
13 |
Open the text file in write format. |
14 |
If the text file does not open, print an error message. |
15-18 |
Create a loop that prints the array of generated I and Q data samples to the text file. |
19 |
Close the text file. |
This step has two sets of code:
Interleaving and byte swapping I and Q data for little endian order
Interleaving I and Q data for big endian order
For more information on byte order, see Little Endian and Big Endian (Byte Order).
|
The PXB expects data in big endian order. |
Line |
Code – Interleaving and Byte Swapping for Little Endian Order
|
20 |
char iqbuffer[NUMSAMPLES*4]; |
21 |
for (index=0; index<NUMSAMPLES; index++) |
22 |
{ |
23 |
short ivalue = idata[index]; |
24 |
short qvalue = qdata[index]; |
25 |
iqbuffer[index*4] = (ivalue >> 8) & 0xFF; |
26 |
iqbuffer[index*4+1] = ivalue & 0xFF; |
27 |
iqbuffer[index*4+2] = (qvalue >> 8) & 0xFF; |
28 |
iqbuffer[index*4+3] = qvalue & 0xFF; |
29 |
} |
30 |
return 0; |
Line |
Code – Description Interleaving and Byte Swapping for Little Endian Order |
||
20 |
Define a character array to store the interleaved I and Q data. The character array makes byte swapping easier, since each array location accepts only 8 bits (1 byte). The array size increases by four times to accommodate two bytes of I data and two bytes of Q data. |
||
21-29 |
Create a loop to do the following:
|
Line |
Code – Interleaving I and Q data for Big Endian Order
|
20 |
short iqbuffer[NUMSAMPLES*2]; |
21 |
for (index=0; index<NUMSAMPLES; index++) |
22 |
{ |
23 |
iqbuffer[index*2] = idata[index]; |
24 |
iqbuffer[index*2+1] = qdata[index]; |
25 |
} |
26 |
return 0; |
Line |
Code – Description Interleaving I and Q data for Big Endian Order |
||
20 |
Define a 16-bit integer (short) array to store the interleaved I and Q data. The array size increases by two times to accommodate two bytes of I data and two bytes of Q data.
|
||
21-25 |
Create a loop to do the following:
|
This topic examines methods of downloading I/Q waveform data created in MATLAB (a simulation software) and C++ (an advanced programming language).
There are two steps in the process of downloading an I/Q waveform:
Open a connection session.
Download the I/Q data.
The following code establishes a LAN connection with the PXB or prints an error message if the session is not opened successfully.
Line |
Code – Open a Connection Session
|
1 |
char* instOpenString ="lan[hostname or IP address]"; |
2 |
INST id=iopen(instOpenString); |
3 |
if (!id) |
4 |
{ |
5 |
fpringf(stderr, "iopen failed (%s)\n", instOpenString); |
6 |
return -1; |
7 |
} |
Line |
Code – Description Open a Connection Session |
1 |
Assign the PXB’s LAN hostname, IP address, or GPIB address to a character string.
|
2 |
Open a connection session with the PXB to download the generated I/Q data. The SICL function
This occurs if the connection fails.
|
3-7 |
If id = 0, the program prints out the error message and exits the program. |
The following code sends the SCPI command and downloads the generated waveform data to the PXB.
Line |
Code – Download the I/Q Data
|
8 |
int bytesToSend; |
9 |
bytesToSend = numsamples*4; |
10 |
char s[20]; |
11 |
char cmd[200]; |
12 |
sprintf(s, "%d", bytesToSend); |
13 |
sprintf(cmd, ":MEM:DATA\"NVWFM1:FILE1\", #%d%d", strlen(s), bytesToSend); |
14 |
iwrite(id, cmd, strlen(cmd), 0, 0); |
15 |
iwrite(id, iqbuffer, bytesToSend, 0, 0); |
16 |
iwrite(id, "\n", 1, 1, 0); |
Line |
Code – Description Download the I/Q data |
8 |
Define an integer variable (bytesToSend) to store the number of bytes to send to the PXB. |
9 |
Calculate the total number of bytes, and store the value in the integer variable defined in line 8. In this code, numsamples contains the number of waveform points, not the number of bytes. Because it takes four bytes of data, two I bytes and two Q bytes, to create one waveform point, we have to multiply numsamples by four. This is shown in the following example: numsamples = 512 waveform points numsamples X 4 = 2048 (four bytes per point) bytesToSend = 2048 (numsamples X 4) For information on setting the number of waveform points, see Create I and Q data. |
10 |
Create a string large enough to hold the bytesToSend value as characters. In this code, string s is set to 20 bytes (20 characters—one character equals one byte). |
11 |
Create a string and set its length (cmd[200]) to hold the SCPI command syntax and parameters. In this code, we define the string length as 200 bytes (200 characters). |
12 |
Store the value of bytesToSend in string s. For example, if bytesToSend = 2048; s = ”2048” sprintf() is a standard function in C++, which writes string data to a string variable. |
13 |
Store the SCPI command syntax and parameters in the string cmd. The SCPI command prepares the PXB to accept the data.
|
14 |
Send the SCPI command stored in the string cmd to the PXB, which is represented by the session id.
|
15 |
Send the generated waveform data stored in the I/Q array (iqbuffer) to the PXB.
In many programming languages, there are two methods to send SCPI commands and data:
For your programming language, you must find and use the equivalent of method two. Otherwise you may only achieve a partial download of the I and Q data. |
16 |
Send the terminating carriage (\n) as the last byte of the waveform data.
To verify the waveform data download, see Playing and Verifying a Downloaded Waveform. |