1// Copyright [2016] Zurich Instruments AG
2//
3// LabOne C API Example
4//
5// This Example demonstrates how to compile an AWG sequencer program and upload
6// it to an instrument using the LabOne API's AWG Module.
7//
8// Prerequisites:
9//
10// The AWG source file specified by the awgSourceFile variable should be a .seqc
11// file and located in the awg/src sub-folder of your Zurich Instruments user
12// folder. The awg/src folder is located on Windows at:
13// C:\Users\danielw\Documents\Zurich Instruments\LabOne\WebServer\awg\src
14// and on Linux at:
15// ~/Zurich\ Instruments/LabOne/WebServer/awg/src/
16//
17// If no AWG source files are available at this location, please start the
18// LabOne User Interface, open the AWG Tab and open and save one of the example
19// files. It will then be saved to the awg/src directory.
20#include <stdlib.h>
21
22#include "ziAPI.h"
23#include "ziUtils.hpp"
24
25
26int main()
27{
28 // Define the device address of the device to run the example on.
29 const char* deviceAddress = ziUtilsGetEnv("LABONE_DEVICE", "dev2123");
30 printf("ENV LABONE_DEVICE=%s\n", deviceAddress);
31
32 // Address of the data server.
33 const char* dataServer = ziUtilsGetEnv("LABONE_SERVER", "localhost");
34
35 // Port of the data server.
36 const uint16_t port = 8004;
37
38 // Over which interface the connection to the
39 // device should be established. Can be either
40 // - 1: "1GbE" - Ethernet
41 // - 2: "USB" - USB
42 // - 3: "PCIe" - PCIe
43 const char* deviceInterface = "1GbE";
44
45 // The filename of the AWG sequencer program to compile and load, see the
46 // comments at the top of this file to see where this file is located.
47 const char* awgSourceFile = "ziAWG_functional_for.seqc";
48
49 ZIConnection conn = nullptr;
50
51 if (isError(ziAPIInit(&conn)))
52 {
53 return 1;
54 }
55
56 ziAPISetDebugLevel(0);
57 ziAPIWriteDebugLog(0, "Logging enabled.");
58
59 try
60 {
61 checkError(
62 ziAPIConnectEx(conn, dataServer, port, ZI_API_VERSION_6, nullptr));
63 checkError(
64 ziAPIConnectDevice(conn, deviceAddress, deviceInterface, nullptr));
65 ziApiServerVersionCheck(conn);
66 int awgIndex = 0;
67
68 // Disable the AWG.
69 char path[1024];
70 ziAPIWriteDebugLog(0, "Disabling AWG.");
71 snprintf(path, sizeof(path), "/%s/awgs/%d/enable", deviceAddress, awgIndex);
72 checkError(ziAPISetValueI(conn, path, 0));
73 ziAPISync(conn);
74
75 char message[1024];
76 ZIModuleHandle awgModule;
77 checkError(ziAPIModCreate(conn, &awgModule, "awgModule"));
78 snprintf(
79 message,
80 sizeof(message),
81 "Module created, handle: %" PRIu64 ".",
82 awgModule);
83 ziAPIWriteDebugLog(0, message);
84 checkError(ziAPIModSetString(conn, awgModule, "device", deviceAddress));
85
86 /* Start the module thread. */
87 checkError(ziAPIModExecute(conn, awgModule));
88 ziAPIWriteDebugLog(0, "Executing the module.");
89 checkError(ziAPIModSetString(
90 conn, awgModule, "compiler/sourcefile", awgSourceFile));
91
92 // Note: When transferring the AWG sequence program as a 'sourcestring'
93 // compilation starts automatically. When specifying the AWG from a source
94 // file the compiler needs to be started explicitly.
95 checkError(ziAPIModSetIntegerData(conn, awgModule, "compiler/start", 1));
96
97 ZIIntegerData compilerStatus = -1;
98 while (compilerStatus == -1)
99 {
100 sleep(500); // [ms]
101 checkError(ziAPIModGetInteger(
102 conn, awgModule, "compiler/status", &compilerStatus));
103 }
104 unsigned int compilerStatusstringLength = 0;
105 char compilerStatusstring[1024] = "";
106 checkError(ziAPIModGetString(
107 conn,
108 awgModule,
109 "compiler/statusstring",
110 compilerStatusstring,
111 &compilerStatusstringLength,
112 (unsigned int)1024));
113 if (compilerStatusstringLength == 0)
114 {
115 ziAPIWriteDebugLog(
116 3,
117 "ziAPIModGetString returned string length 0 whilst getting "
118 "compiler/statusstring: "
119 "Either an error occurred or the provided buffer was not large "
120 "enough.");
121 }
122 else if (compilerStatus == 1)
123 {
124 snprintf(
125 message,
126 sizeof(message),
127 "Compilation failed; compiler returned status string: %s.",
128 compilerStatusstring);
129 ziAPIWriteDebugLog(0, message);
130 return 1;
131 }
132 else
133 {
134 // Success: Upload the waveform.
135 if (compilerStatus == 0)
136 {
137 snprintf(
138 message,
139 sizeof(message),
140 "Compilation successful with no warnings, compiler status string: "
141 "%s.",
142 compilerStatusstring);
143 ziAPIWriteDebugLog(0, message);
144 }
145 else if (compilerStatus == 2)
146 {
147 snprintf(
148 message,
149 sizeof(message),
150 "Compilation successful, but with warnings: %s.",
151 compilerStatusstring);
152 ziAPIWriteDebugLog(0, message);
153 }
154 // Ensure that the upload of the waveform to the device has finished.
155 ZIDoubleData progress = 0.0;
156 while (progress < 1.0)
157 {
158 sleep(200); // [ms]
159 checkError(ziAPIModGetDouble(conn, awgModule, "progress", &progress));
160 }
161 ziAPIWriteDebugLog(0, "Uploading waveform to the device finished.");
162
163 snprintf(
164 path, sizeof(path), "/%s/awgs/%d/enable", deviceAddress, awgIndex);
165 checkError(ziAPISetValueI(conn, path, 1));
166 ziAPIWriteDebugLog(0, "Enabled the AWG.");
167 }
168 // Release module resources. Especially important if modules are created
169 // inside a loop to prevent excessive resource consumption.
170 checkError(ziAPIModClear(conn, awgModule));
171 ziAPIDisconnect(conn);
172 }
173 catch (std::runtime_error& e)
174 {
175 char extErrorMessage[1024] = "";
176 ziAPIGetLastError(conn, extErrorMessage, 1024);
177 fprintf(stderr, "Error: %s\ndetails: %s\n", e.what(), extErrorMessage);
178 return 1;
179 }
180 ziAPIDestroy(conn);
181
182 return 0;
183}