AWG Module
The AWG module allows programmers to access the functionality available in the LabOne User Interface AWG tab. It allows users to compile and upload sequencer programs to the arbitrary waveform generator on UHF and HDAWG instruments from any of the LabOne APIs.
This chapter only explains the specifics for working with an AWG from an API; reference documentation of the LabOne AWG Sequencer Programming Language can be found in the UHF or HDAWG User Manual.
example_awg.py
, which also generates the expected waveform and cross-correlates it with the measured waveform in order to overlay the expected signal on the measurement data.Getting Started with the AWG Module
The following API examples demonstrating AWG Module use are available:
-
MATLAB and Python,
example_awg.{py,m}
: Compiles and uploads an AWG sequencer program from a string. It demonstrates how to define waveforms using the four methods listed below in Methods to define Waveforms in Sequencer Programs. Separate versions of these examples are available for both UHF and HDAWG instruments. -
MATLAB and Python,
example_awg_sourcefile.{py,m}
: Demonstrates how to compile and upload an AWG sequencer program from a.seqc
file. Separate versions of these examples are available for both UHF and HDAWG instruments. -
LabVIEW,
ziExample-UHFLI-Module-AWG.vi
: Compiles and uploads an AWG sequencer program from a string and captures the generated waveform in the scope (UHF only). -
.NET,
ExampleAwgModule()
(inExamples.cs
): Compiles and uploads an AWG sequencer program from a string. It demonstrates how to define waveforms using the four methods listed below in Methods to define Waveforms in Sequencer Programs. -
C API,
ExampleAWGUpload.c
: Demonstrates how to compile and upload an AWG sequencer program from a.seqc
file.
Sequencer Program Compilation and Upload
Programming an AWG with a sequencer program is a 2-step process. First, the source code must be compiled to a binary ELF file and secondly the ELF file must be uploaded from the PC to the AWG on the UHF or HDAWG instrument. Both steps are performed by an instance of the AWG Module regardless of whether the module is used in the API or the LabOne User Interface’s AWG Sequencer tab.
Compilation
An AWG sequencer program can be provided to the AWG module for compilation as either a:
|
Upload
If the |
Methods to define Waveforms in Sequencer Programs
The waveforms played by an AWG sequencer program can be defined, or in the last case, modified, using the following four methods. These methods are demonstrated by the examples listed in Getting Started with the AWG Module.
-
By using one of the waveform generation functions such as
sine()
,sinc()
,gauss()
, etc. defined in the LabOne AWG Sequencer programming language. See the UHF, HDAWG or SHFSG User Manual for full reference documentation. -
By defining a
placeholder
waveform and later loading the actual waveform from the API. This method is optimal, especially for long waveforms.[1] -
By defining a waveform in a file, either with a floating point format in a CSV file, or a binary file.
API vector transfer
The waveform must be first defined in the sequence, either as placeholder
or as completely defined waveform with valid samples. In the first case, the compiler will only allocate the required memory and the waveform content is loaded later. The waveform definition must specify the length and eventual presence of markers. This should be respected later when the actual waveform is loaded.
The waveform can be loaded from the API using the set
command to write waveform data the following nodes:
UHF |
/DEV…/AWGS/0/WAVEFORM/WAVES/<index> |
HDAWG |
/DEV…/AWGS/[0-3]/WAVEFORM/WAVES/<index> |
SHFSG |
/DEV…/SGCHANNELS/[0-7]/AWG/WAVEFORM/WAVES/<index> [2] |
These nodes are the same regardless of the channel grouping mode on the HDAWG, so for example even when using the 1x8 mode on HDAWG8, waveforms are addressed separately for all 4 AWG cores. Multiple waveform uploads can be combined into one set
command, which reduces upload time (see below). The assignment of a waveform to an index is done directly in the AWG sequence program using the assignWaveIndex
instruction. As example
wave w = placeholder(WFM_SIZE);
assignWaveIndex(1,w, INDEX);
will allocate a waveform of WFM_SIZE
at the index INDEX
.
Dual-channel waveforms
Dual-channel waveform are effectively a single waveform, so there is only one index associated:
|
HDAWG grouped mode
When the HDAWG is configured to work in grouped mode (all modes except 4x2 mode), see section HDAWG Channel Grouping, the waveforms for each AWG core are treated separately, even when they are played together. As in the 4x2 mode, waveforms can be either single- or dual-channel per core. As an example, this sequence
defines one dual-channel waveform on core 1, and one single-channel waveform on core 2. They can be loaded by writing their content to the nodes
|
The waveform nodes use the internal raw format of the instrument and map the hardware capabilities of an AWG core. Thus, each waveform node can hold up to two analog waveforms and four markers. The length, number of waves and the presence of markers must be the same as defined in the sequence. An analog waveform is represented as array of signed int16. The markers are represented as array of int16, with the marker values defined in the four LSB; the other 12 bits must be zeros (see Figure 2).
wave_int16 = int16((1 << 15 - 1) * wave_float);
markers = int16(mk1_out1 * 1 << 0 + mk2_out1 * 1 << 1 +
mk1_out2 * 1 << 2 + mk2_out2 * 1 << 3);
If there is more than one analog waveform and/or markers, the arrays representing them must be interleaved; the order should be the first wave, then the second and finally the markers (see Figure 2).
In Python, it’s convenient to use the helper functions zhinst.utils.convert_awg_waveform
and zhinst.utils.parse_awg_waveform
to write and read these nodes.
When uploading 2 or more waveforms with the Python API, it is recommended to perform the waveform upload with a single set
command. This is possible by combining multiple pairs of waveform addresses and data as a Python list of tuples, and using this list as the argument of the set
command. In this way, the overhead in communication latency is paid only once, and waveform upload is much faster than when issuing a set
command for each waveform. The example below shows both the usage of the helper functions, and the combination of multiple waveform uploads in one set
command.
The |
import zhinst.core
import zhinst.utils
import numpy as np
device = 'dev8000'
daq = zhinst.core.ziDAQServer('localhost', 8004, 6) #Connect to the dataserver
daq.connectDevice(device, '1GbE') #Connect to the device
#Generate a waveform and marker
WFM_SIZE = 1024
wave_a = np.sin(np.linspace(0, 10*np.pi, WFM_SIZE))*np.exp(np.linspace(0, -5, WFM_SIZE))
wave_b = np.sin(np.linspace(0, 20*np.pi, WFM_SIZE))*np.exp(np.linspace(0, -5, WFM_SIZE))
wave_c = np.sin(np.linspace(0, 30*np.pi, WFM_SIZE))*np.exp(np.linspace(0, -5, WFM_SIZE))
marker_a = np.concatenate([ 0b11*np.ones(32), np.zeros(WFM_SIZE-32)]).astype(int)
marker_bc = np.concatenate([0b1111*np.ones(32), np.zeros(WFM_SIZE-32)]).astype(int)
#Convert and send them to the instrument
wave_raw_a = zhinst.utils.convert_awg_waveform(wave_a, markers=marker_a)
wave_raw_bc = zhinst.utils.convert_awg_waveform(wave_b, wave_c, markers=marker_bc)
INDEX1 = 0
INDEX2 = 1
set_cmd = [(f'/{device:s}/awgs/0/waveform/waves/{INDEX1}', wave_raw_a),
(f'/{device:s}/awgs/0/waveform/waves/{INDEX2}', wave_raw_bc) ]
daq.set(set_cmd)
The Python code above corresponds to an AWG sequence program as the one below, which makes use of a single-channel and a dual-channel waveform playback.
wave w_a = placeholder(WFM_SIZE, true, true);
wave w_b = placeholder(WFM_SIZE, true, true);
wave w_c = placeholder(WFM_SIZE, true, true);
assignWaveIndex(1, w_a, INDEX1);
assignWaveIndex(w_b, w_c, INDEX2);
playWave(1, w_a);
playWave(w_b, w_c);
The waveform nodes have the property SILENTWRITE. This means that subscribing to such a node has no effect, i.e. changes to the node will not be returned in |
File on disk
A waveform stored on the disk can be loaded from the sequence by referring to the file name without extension in the sequence program. For example
//Definition inline with playWave
playWave("wave_file");
//Assign first to a wave data type, then use
wave w = "wave_file";
playWave(w)
Two formats are supported, an CSV ASCII based and a binary one. The binary format should be preferred as it offers faster compilation than the CSV format.
The waveform files must be located in the "awg/waveforms" sub-directory of the LabOne user directory (see explanation of directory
).
Binary
The binary format support only single-channel definition. To use dual-channel waveforms, two files holding single-channel waveform can be loaded separately:
wave w1 = 'wave1';
wave w2 = 'wave2';
playWave(1,w1, 2,w2);
The file must use the extension ".wave". Each sample is a word of 16 bits little-endian. The bits are assigned as follow:
-
Bit 15-2: Wave, as 14 bit signed integer
-
Bit 1: Marker 2
-
Bit 0: Marker 1
As example, the waveform [-1.0, 0.0, 1.0], without marker will be saved as 04 80 00 00 FC 7F
. The same waveform with marker1 [1,0,0] and marker2 [1,1,0] would be FD 7F 01 00 02 00
.
By default the AWG compiler loads in memory all the binary waveforms present in the |
ASCII CSV
As alternative to binary waveform, the ASCII CSV format can be used. The CSV file should contain floating-point values in the range from –1.0 to +1.0 and contain one or two columns, corresponding to the single- and dual-channel waveforms. The file must use the extension ".csv". As an example, the following specify a dual-channel wave with a length of 16 samples:
-1.0 0.0 -0.8 0.0 -0.7 0.1 -0.5 0.2 -0.2 0.3 -0.1 0.2 0.1 0.0 0.2 -0.1 0.7 -0.3 1.0 -0.2 0.9 -0.3 0.8 -0.2 0.4 -0.1 0.0 -0.1 -0.5 -0.1 -0.8 0.0
In order to obtain digital marker data from a file, specify a second wave file with integer instead of floating-point values. The marker bits are encoded in the binary representation of the integer (i.e., integer 1 corresponds to the first marker high, 2 corresponds to the second marker high, and 3 corresponds to both bits high). Later in the program add up the analog and the marker waveforms. For instance, if the floating-point analog data are contained in wave_file_analog.csv
and the integer marker data in wave_file_digital.csv
, the following code can be used to combine and play them.
wave w_analog = "wave_file_analog";
wave w_digital = "wave_file_digital";
wave w = w_analog + w_digital;
playWave(w);
As an alternative to specifying analog data as floating-point values in one file, and marker data as integer values in a second file, both may be combined into one file containing integer values. The integer values in that file should be 18-bit unsigned integers with the two least significant bits being the markers. The values are mapped to 0 ⇒ -FS, 262143 ⇒ +FS, with FS equal to the full scale. This integer version of the CSV format is not to be confused with the binary file format documented previously. To optimize compilation speed, the binary format should be preferred over both versions of the CSV format.
HDAWG Channel Grouping
This section explains how to configure the index
parameter
and which AWGS node branch must be used for different channel grouping
configurations. The channel grouping is defined by the value of the the
node /DEV…./SYSTEM/AWG/CHANNELGROUPING as follows:
- 0:
-
Use the outputs in groups of 2; each sequencer program controls 2 outputs. Each group n=0,1,2,3 of AWGs (respectively n=0,1 on HDAWG4 instruments) is configured by the /DEV…./AWGS/n branches. Each of these 4 groups requires its own instance of the AWG Module and
index
should be set to n=0,1,2,3 for each group accordingly. - 1:
-
Use the outputs in groups of 4; each sequencer program controls 4 outputs. Each group n=0,1 of AWGs (respectively n=0 on HDAWG4 instruments) is configured by the /DEV…./AWGS/0 and /DEV…./AWGS/2 branches. Each of these two groups requires its own instance of the AWG Module and
index
should be set to n=0,1 for each group accordingly. For HDAWG4 instruments, there is only one group of 4 outputs which is configured by the /DEV…./AWGS/0 branch. - 2:
-
HDAWG8 devices only. Use the outputs in a single group of 8; the (single) sequencer program controls 8 outputs. There is only one group (n=0) of 8 AWGs which is configured by the /DEV…./AWGS/0 branch. Only one instance of the AWG Module is required and its value of
index
should be 0.
Value of CHANNELGROUPING | Number of Cores | AWG Core | Corresponding device AWG branch index | Value of index |
---|---|---|---|---|
0 |
4 |
1 |
/DEV…./AWGS/0 |
0 |
2 |
/DEV…./AWGS/1 |
1 |
||
3 |
/DEV…./AWGS/2 |
2 |
||
4 |
/DEV…./AWGS/3 |
3 |
||
1 |
2 |
1 |
/DEV…./AWGS/0 |
0 |
2 |
/DEV…./AWGS/2 |
1 |
||
2 |
1 |
1 |
/DEV…./AWGS/0 |
0 |
Value of CHANNELGROUPING | Number of Cores | AWG Core | Corresponding device AWG branch index | Value of index |
---|---|---|---|---|
0 |
2 |
1 |
/DEV…./AWGS/0 |
0 |
2 |
/DEV…./AWGS/1 |
1 |
||
1 |
1 |
1 |
/DEV…./AWGS/0 |
0 |
AWG Module Node Tree
The following section contains reference documentation for the settings and measurement data available on the AWG module.
Since these settings and data streams may be written and read using the LabOne APIs (Application Programming Interfaces) this section is of particular interest to users who would like to perform measurements programmatically via LabVIEW, Python, MATLAB, .NET or C.
awg
Read, Write Integer (64 bit) None Start the AWG sequencers. In MDS mode, this will enable all devices in the correct order.
/awg/enable
Properties:
Type:
Unit:
compiler
Read, Write String None The filename of an AWG sequencer program file to compile and load. The file must be located in the "awg/src" sub-directory of the LabOne user directory. This directory path is provided by the value of the read-only directory parameter.
/compiler/sourcefile
Properties:
Type:
Unit:
Read, Write String None A string containing an AWG sequencer program may directly loaded to this parameter using the module command setString. This allows compilation and upload of a sequencer program without saving it to a file first. Compilation starts automatically after compiler/sourcestring has been set.
/compiler/sourcestring
Properties:
Type:
Unit:
Read, Write Integer (64 bit) None Set to 1 to start compiling the AWG sequencer program specified by compiler/ sourcefile. The module sets compiler/ start to 0 once compilation has successfully completed (or failed). If compiler/upload is enabled then the sequencer program will additionally be uploaded to the AWG upon after successful compilation.
/compiler/start
Properties:
Type:
Unit:
Read Integer (enumerated) None Compilation status -1 Idle. 0 Compilation successful. 1 Compilation failed. 2 Compilation completed with warnings.
/compiler/status
Properties:
Type:
Unit:
Read String None Status message of the compiler.
/compiler/statusstring
Properties:
Type:
Unit:
Read, Write Integer (64 bit) None Specify whether the sequencer program should be automatically uploaded to the AWG following successful compilation.
/compiler/upload
Properties:
Type:
Unit:
Read, Write String None A comma-separated list of waveform CSV files to be used by the AWG sequencer program.
/compiler/waveforms
Properties:
Type:
Unit:
device
Read, Write String None The target device for AWG sequencer programs upload, e.g. 'dev2006'.
/device
Properties:
Type:
Unit:
directory
Read, Write String None The path of the LabOne user directory. The AWG Module uses the following subdirectories in the LabOne web server directory: "awg/src": Contains AWG sequencer program source files (user created); "awg/elf": Contains compiled AWG binary (ELF) files (created by the module); "awg/waves": Contains CSV waveform files (user created).
/directory
Properties:
Type:
Unit:
elf
Read Integer (64 bit) None The checksum of the generated ELF file.
/elf/checksum
Properties:
Type:
Unit:
Read, Write String None The filename of the compiled binary ELF file. If not set, the name is automatically set based on the source filename. The ELF file will be saved by the AWG Module in the "awg/elf" sub-directory of the LabOne user directory. This directory path is provided by the value of the read-only directory parameter.
/elf/file
Properties:
Type:
Unit:
Read Integer (enumerated) None Status of the ELF file upload. -1 Idle. 0 Upload successful. 1 Upload failed. 2 Upload in progress.
/elf/status
Properties:
Type:
Unit:
Read, Write Integer (64 bit) None Set to 1 to start uploading the AWG sequencer program to the device. The module sets elf/upload to 0 once the upload has finished.
/elf/upload
Properties:
Type:
Unit:
index
Read, Write Integer (64 bit) None The index of the current AWG Module to use when running with multiple AWG groups. See section on channel grouping in the manual for further explanation.
/index
Properties:
Type:
Unit:
mds
Read, Write Integer (64 bit) None The MDS group (multiDeviceSyncModule/group) to use for synchronized AWG playback.
/mds/group
Properties:
Type:
Unit:
progress
Read Double None Reports the progress of the upload as a value between 0 and 1.
/progress
Properties:
Type:
Unit:
sequencertype
Read, Write Integer (enumerated) None Type of sequencer to compile for. For all devices but the SHFQC, the sequencer type is deduced from the device type, and this node is ignored. For the SHFQC, the sequencer type must be defined ("qa" or "sg"). 0 The sequencer type is deduced from the device type (for all devices but the SHFQC). 1 QA sequencer 2 SG sequencer
/sequencertype
Properties:
Type:
Unit:
auto-detect
qa
sg