67typedef long Device_Link;
68typedef long Device_Flags;
69typedef long Device_ErrorCode;
72 Device_ErrorCode error;
78 unsigned long lock_timeout;
83 Device_ErrorCode error;
85 unsigned short abortPort;
86 unsigned long maxRecvSize;
91 unsigned long io_timeout;
92 unsigned long lock_timeout;
95 unsigned int data_len;
101 Device_ErrorCode error;
107 unsigned long requestSize;
108 unsigned long io_timeout;
109 unsigned long lock_timeout;
115 Device_ErrorCode error;
118 unsigned int data_len;
123#define create_link 10
124#define device_write 11
125#define device_read 12
126#define destroy_link 23
128#define VXI11_DEFAULT_TIMEOUT 10000
129#define VXI11_READ_TIMEOUT 2000
130#define VXI11_CLIENT CLIENT
131#define VXI11_LINK Create_LinkResp
132#define VXI11_MAX_CLIENTS 256
133#define VXI11_NULL_READ_RESP 50
136#define VXI11_NULL_WRITE_RESP 51
140 VXI11_CLIENT *client;
144#define DEVICE_CORE 0x0607AF
145#define DEVICE_CORE_VERSION 1
146#define RCV_END_BIT 0x04
147#define RCV_CHR_BIT 0x02
149char VXI11_IP_ADDRESS[VXI11_MAX_CLIENTS][20];
150CLIENT *VXI11_CLIENT_ADDRESS[VXI11_MAX_CLIENTS];
151int VXI11_DEVICE_NO = 0;
152int VXI11_LINK_COUNT[VXI11_MAX_CLIENTS];
154static struct timeval TIMEOUT = {25, 0};
166bool sc(
const char *con,
const char *var);
168int agilent_init(
CLINK *clink);
169int agilent_set_averages(
CLINK *clink,
int no_averages);
170void agilent_set_for_auto(
CLINK *clink);
171long agilent_get_data(
CLINK *clink,
char chan,
char *buf,
unsigned long buf_len,
unsigned long timeout);
172long agilent_get_data(
CLINK *clink,
char chan,
int digitise,
char *buf,
unsigned long buf_len,
unsigned long timeout);
173int agilent_get_preamble(
CLINK *clink,
char *buf,
unsigned long buf_len);
174void agilent_scope_channel_str(
char chan,
char *source);
175int agilent_set_for_capture(
CLINK *clink,
double s_rate,
long npoints,
unsigned long timeout);
176long agilent_calculate_no_of_bytes(
CLINK *clink,
char chan,
unsigned long timeout);
178int vxi11_open_device(
const char *ip,
CLINK *clink);
179int vxi11_open_device(
const char *ip,
CLINK *clink,
char *device);
180int vxi11_open_device(
const char *ip, CLIENT **client,
VXI11_LINK **link,
char *device);
181int vxi11_open_link(
const char *ip, CLIENT **client,
VXI11_LINK **link,
char *device);
182int vxi11_send(
CLINK *clink,
const char *cmd);
183int vxi11_send(
CLINK *clink,
const char *cmd,
unsigned long len);
184int vxi11_send(CLIENT *client,
VXI11_LINK *link,
const char *cmd);
185int vxi11_send(CLIENT *client,
VXI11_LINK *link,
const char *cmd,
unsigned long len);
186int vxi11_close_device(
const char *ip,
CLINK *clink);
187int vxi11_close_device(
const char *ip, CLIENT *client,
VXI11_LINK *link);
188int vxi11_close_link(
const char *ip, CLIENT *client,
VXI11_LINK *link);
189double vxi11_obtain_double_value(
CLINK *clink,
const char *cmd);
190double vxi11_obtain_double_value(
CLINK *clink,
const char *cmd,
unsigned long timeout);
191long vxi11_send_and_receive(
CLINK *clink,
const char *cmd,
char *buf,
unsigned long buf_len,
unsigned long timeout);
192long vxi11_receive(
CLINK *clink,
char *buffer,
unsigned long len);
193long vxi11_receive(
CLINK *clink,
char *buffer,
unsigned long len,
unsigned long timeout);
194long vxi11_obtain_long_value(
CLINK *clink,
const char *cmd,
unsigned long timeout);
195long vxi11_obtain_long_value(
CLINK *clink,
const char *cmd);
196long vxi11_receive_data_block(
CLINK *clink,
char *buffer,
unsigned long len,
unsigned long timeout);
200enum clnt_stat destroy_link_1(Device_Link *argp,
Device_Error *clnt_res, CLIENT *clnt);
205bool_t xdr_Device_ErrorCode(XDR *xdrs, Device_ErrorCode *objp);
206bool_t xdr_Device_Link(XDR *xdrs, Device_Link *objp);
209bool_t xdr_Device_Flags(XDR *xdrs, Device_Flags *objp);
214int main(
int argc,
char **argv) {
215 const char *progname;
216 const char *serverIP =
nullptr;
218 FILE *f_wf =
nullptr;
219 char wfname[256] = {0};
222 unsigned long timeout = VXI11_DEFAULT_TIMEOUT;
224 long bytes_returned = 0;
226 bool got_scope_channel =
false;
227 bool got_file =
false;
228 bool got_no_averages =
false;
233 double actual_s_rate = 0.0;
234 long actual_npoints = 0;
235 CLINK *clink =
nullptr;
238 double vgain = 0.0, voffset = 0.0, hinterval = 0.0, hoffset = 0.0;
241 clink =
new (std::nothrow)
CLINK;
243 std::fprintf(stderr,
"Error: Memory allocation for CLINK failed.\n");
249 while (index < argc) {
250 if (sc(argv[index],
"-filename") || sc(argv[index],
"-f") || sc(argv[index],
"-file")) {
251 if (index + 1 >= argc) {
252 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
256 std::snprintf(wfname,
sizeof(wfname),
"%s.sdds", argv[++index]);
261 if (sc(argv[index],
"-ip") || sc(argv[index],
"-ip_address") || sc(argv[index],
"-IP")) {
262 if (index + 1 >= argc) {
263 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
267 serverIP = argv[++index];
272 if (sc(argv[index],
"-channel") || sc(argv[index],
"-c") || sc(argv[index],
"-scope_channel")) {
273 if (index + 1 >= argc) {
274 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
278 std::sscanf(argv[++index],
"%c", &chnl);
279 got_scope_channel =
true;
283 if (sc(argv[index],
"-sample_rate") || sc(argv[index],
"-s") || sc(argv[index],
"-rate")) {
284 if (index + 1 >= argc) {
285 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
289 std::sscanf(argv[++index],
"%lg", &s_rate);
293 if (sc(argv[index],
"-no_points") || sc(argv[index],
"-n") || sc(argv[index],
"-points")) {
294 if (index + 1 >= argc) {
295 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
299 std::sscanf(argv[++index],
"%ld", &npoints);
303 if (sc(argv[index],
"-averages") || sc(argv[index],
"-a") || sc(argv[index],
"-aver")) {
304 if (index + 1 >= argc) {
305 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
309 std::sscanf(argv[++index],
"%d", &no_averages);
310 got_no_averages =
true;
314 if (sc(argv[index],
"-timeout") || sc(argv[index],
"-t")) {
315 if (index + 1 >= argc) {
316 std::fprintf(stderr,
"Error: Missing value for %s.\n", argv[index]);
320 std::sscanf(argv[++index],
"%lu", &timeout);
324 std::fprintf(stderr,
"Warning: Unknown argument %s skipped.\n", argv[index]);
328 if (!got_file || !got_scope_channel || !got_ip) {
329 std::fprintf(stderr,
"%s: Grabs a waveform from an Agilent scope via Ethernet.\n", progname);
330 std::fprintf(stderr,
"Usage: %s [required arguments] [optional arguments]\n\n", progname);
331 std::fprintf(stderr,
"Required Arguments:\n");
332 std::fprintf(stderr,
" -ip, -ip_address, -IP IP address of the scope (e.g., 128.243.74.232)\n");
333 std::fprintf(stderr,
" -f, -filename, -file Filename (without extension)\n");
334 std::fprintf(stderr,
" -c, -channel, -scope_channel Scope channel (1,2,3,4,A,B,C,D)\n\n");
335 std::fprintf(stderr,
"Optional Arguments:\n");
336 std::fprintf(stderr,
" -t, -timeout Timeout in milliseconds (default: 10000 ms)\n");
337 std::fprintf(stderr,
" -s, -sample_rate, -rate Set sample rate (e.g., 1e9 for 1 GS/s)\n");
338 std::fprintf(stderr,
" -n, -no_points, -points Set minimum number of acquisition points\n");
339 std::fprintf(stderr,
" -a, -averages, -aver Set number of averages (<=0 means none)\n\n");
340 std::fprintf(stderr,
"Output:\n");
341 std::fprintf(stderr,
" filename.sdds ASCII data of waveform\n\n");
342 std::fprintf(stderr,
"Example:\n");
343 std::fprintf(stderr,
" %s -ip 128.243.74.232 -f output -c 2 -s 1e9\n", progname);
348 f_wf = std::fopen(wfname,
"w");
349 if (f_wf !=
nullptr) {
350 if (vxi11_open_device(serverIP, clink) != 0) {
351 std::fprintf(stderr,
"Error: Failed to open device.\n");
356 if (agilent_init(clink) != 0) {
357 std::fprintf(stderr,
"Error: Initialization failed.\n");
358 vxi11_close_device(serverIP, clink);
363 agilent_set_for_capture(clink, s_rate, npoints, timeout);
365 if (got_no_averages) {
366 if (agilent_set_averages(clink, no_averages) != 0) {
367 std::fprintf(stderr,
"Warning: Failed to set averages.\n");
371 buf_size = agilent_calculate_no_of_bytes(clink, chnl, timeout);
372 buf =
new (std::nothrow)
char[buf_size];
374 std::fprintf(stderr,
"Error: Memory allocation for buffer failed.\n");
375 vxi11_close_device(serverIP, clink);
380 hinterval = vxi11_obtain_double_value(clink,
":WAV:XINC?", timeout);
381 hoffset = vxi11_obtain_double_value(clink,
":WAV:XORIGIN?");
382 vgain = vxi11_obtain_double_value(clink,
":WAV:YINC?");
383 voffset = vxi11_obtain_double_value(clink,
":WAV:YORIGIN?");
385 bytes_returned = agilent_get_data(clink, chnl, 0, buf, buf_size, timeout);
386 if (bytes_returned <= 0) {
387 std::fprintf(stderr,
"Error: Problem reading the data.\n");
390 vxi11_close_device(serverIP, clink);
395 actual_s_rate = vxi11_obtain_double_value(clink,
":ACQ:SRAT?");
396 actual_npoints = vxi11_obtain_long_value(clink,
":ACQ:POINTS?");
397 std::printf(
"Sample rate used: %g (%g GSa/s); acquisition points: %ld\n", actual_s_rate, (actual_s_rate / 1e9), actual_npoints);
399 agilent_set_for_auto(clink);
402 std::fprintf(f_wf,
"SDDS1\n");
403 std::fprintf(f_wf,
"¶meter name=VerticalGain, type=double, &end\n");
404 std::fprintf(f_wf,
"¶meter name=VerticalOffset, type=double, &end\n");
405 std::fprintf(f_wf,
"¶meter name=HorizontalInterval, type=double, &end\n");
406 std::fprintf(f_wf,
"¶meter name=HorizontalOffset, type=double, &end\n");
407 std::fprintf(f_wf,
"&column name=Index, type=long, &end\n");
408 std::fprintf(f_wf,
"&column name=Waveform, type=double, &end\n");
409 std::fprintf(f_wf,
"&column name=Timebase, type=double, &end\n");
410 std::fprintf(f_wf,
"&column name=DelayedTimebase, type=double, &end\n");
411 std::fprintf(f_wf,
"&data mode=ascii, &end\n");
412 std::fprintf(f_wf,
"%lg\n", vgain);
413 std::fprintf(f_wf,
"%lg\n", voffset);
414 std::fprintf(f_wf,
"%lg\n", hinterval);
415 std::fprintf(f_wf,
"%lg\n", hoffset);
416 std::fprintf(f_wf,
"\t%ld\n", bytes_returned / 2);
418 for (i = 0; i < bytes_returned; i += 2) {
419 std::memcpy(&val, buf + i, 2);
420 std::fprintf(f_wf,
"%ld %lg %lg %lg\n", (i / 2), val * vgain - voffset, (i / 2) * hinterval, (i / 2) * hinterval + hoffset);
426 vxi11_close_device(serverIP, clink);
430 std::fprintf(stderr,
"Error: Could not open file '%s' for writing.\n", wfname);
437bool sc(
const char *con,
const char *var) {
438 return (std::strcmp(con, var) == 0);
441int vxi11_open_device(
const char *ip,
CLINK *clink) {
443 std::strncpy(device,
"inst0",
sizeof(device));
445 return vxi11_open_device(ip, clink, device);
448int vxi11_open_device(
const char *ip, CLIENT **client,
VXI11_LINK **link,
char *device) {
451 *client = clnt_create(
const_cast<char *
>(ip), DEVICE_CORE, DEVICE_CORE_VERSION,
"tcp");
453 *client = clnt_create(ip, DEVICE_CORE, DEVICE_CORE_VERSION,
"tcp");
456 if (*client ==
nullptr) {
458 clnt_pcreateerror(
const_cast<char *
>(ip));
460 clnt_pcreateerror(ip);
465 return vxi11_open_link(ip, client, link, device);
468int vxi11_open_device(
const char *ip,
CLINK *clink,
char *device) {
473 for (l = 0; l < VXI11_MAX_CLIENTS; l++) {
474 if (std::strcmp(ip, VXI11_IP_ADDRESS[l]) == 0) {
481 if (VXI11_DEVICE_NO >= VXI11_MAX_CLIENTS) {
482 std::fprintf(stderr,
"Error: Maximum of %d clients allowed.\n", VXI11_MAX_CLIENTS);
483 ret = -VXI11_MAX_CLIENTS;
485 ret = vxi11_open_device(ip, &(clink->client), &(clink->link), device);
486 std::strncpy(VXI11_IP_ADDRESS[VXI11_DEVICE_NO], ip,
sizeof(VXI11_IP_ADDRESS[0]) - 1);
487 VXI11_IP_ADDRESS[VXI11_DEVICE_NO][
sizeof(VXI11_IP_ADDRESS[0]) - 1] =
'\0';
488 VXI11_CLIENT_ADDRESS[VXI11_DEVICE_NO] = clink->client;
489 VXI11_LINK_COUNT[VXI11_DEVICE_NO] = 1;
493 clink->client = VXI11_CLIENT_ADDRESS[device_no];
494 ret = vxi11_open_link(ip, &(clink->client), &(clink->link), device);
495 VXI11_LINK_COUNT[device_no]++;
500int vxi11_open_link(
const char *ip, CLIENT **client,
VXI11_LINK **link,
char *device) {
505 link_parms.clientId =
reinterpret_cast<intptr_t
>(*client);
506 link_parms.lockDevice = 0;
507 link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
508 link_parms.device = device;
512 std::fprintf(stderr,
"Error: Memory allocation for Create_LinkResp failed.\n");
516 if (create_link_1(&link_parms, *link, *client) != RPC_SUCCESS) {
518 clnt_perror(*client,
const_cast<char *
>(ip));
520 clnt_perror(*client, ip);
530 return clnt_call(clnt, create_link,
531 reinterpret_cast<xdrproc_t
>(xdr_Create_LinkParms),
reinterpret_cast<caddr_t
>(argp),
532 reinterpret_cast<xdrproc_t
>(xdr_Create_LinkResp),
reinterpret_cast<caddr_t
>(clnt_res),
538#if defined(SOLARIS) && !defined(_LP64)
544 if (xdrs->x_op == XDR_ENCODE) {
545 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
546 if (buf ==
nullptr) {
547 if (!xdr_long(xdrs, &objp->clientId))
549 if (!xdr_bool(xdrs, &objp->lockDevice))
551 if (!xdr_u_long(xdrs, &objp->lock_timeout))
555 IXDR_PUT_INT32(buf, objp->clientId);
556 IXDR_PUT_BOOL(buf, objp->lockDevice);
557 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
559 if (!xdr_string(xdrs, &objp->device, ~0))
562 }
else if (xdrs->x_op == XDR_DECODE) {
563 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
564 if (buf ==
nullptr) {
565 if (!xdr_long(xdrs, &objp->clientId))
567 if (!xdr_bool(xdrs, &objp->lockDevice))
569 if (!xdr_u_long(xdrs, &objp->lock_timeout))
573 objp->clientId = IXDR_GET_INT32(buf);
574 objp->lockDevice = IXDR_GET_BOOL(buf);
575 objp->lock_timeout = IXDR_GET_U_INT32(buf);
577 if (!xdr_string(xdrs, &objp->device, ~0))
582 if (!xdr_long(xdrs, &objp->clientId))
584 if (!xdr_bool(xdrs, &objp->lockDevice))
586 if (!xdr_u_long(xdrs, &objp->lock_timeout))
588 if (!xdr_string(xdrs, &objp->device, ~0))
594 if (!xdr_Device_ErrorCode(xdrs, &objp->error))
596 if (!xdr_Device_Link(xdrs, &objp->lid))
598 if (!xdr_u_short(xdrs, &objp->abortPort))
600 if (!xdr_u_long(xdrs, &objp->maxRecvSize))
605bool_t xdr_Device_ErrorCode(XDR *xdrs, Device_ErrorCode *objp) {
606 return xdr_long(xdrs, objp);
609bool_t xdr_Device_Link(XDR *xdrs, Device_Link *objp) {
610 return xdr_long(xdrs, objp);
613int agilent_init(
CLINK *clink) {
615 ret = vxi11_send(clink,
":SYSTEM:HEADER 0");
617 std::fprintf(stderr,
"Error: Could not send ':SYSTEM:HEADER 0' command.\n");
620 vxi11_send(clink,
":ACQUIRE:COMPLETE 100");
622 vxi11_send(clink,
":WAVEFORM:BYTEORDER LSBFIRST");
624 vxi11_send(clink,
":WAVEFORM:BYTEORDER MSBFIRST");
626 vxi11_send(clink,
":WAVEFORM:FORMAT BINARY");
630int vxi11_send(
CLINK *clink,
const char *cmd) {
631 return vxi11_send(clink, cmd, std::strlen(cmd));
634int vxi11_send(
CLINK *clink,
const char *cmd,
unsigned long len) {
635 return vxi11_send(clink->client, clink->link, cmd, len);
638int vxi11_send(CLIENT *client,
VXI11_LINK *link,
const char *cmd) {
639 return vxi11_send(client, link, cmd, std::strlen(cmd));
642int vxi11_send(CLIENT *client,
VXI11_LINK *link,
const char *cmd,
unsigned long len) {
644 int bytes_left =
static_cast<int>(len);
647 send_cmd =
new (std::nothrow)
char[len];
649 std::fprintf(stderr,
"Error: Memory allocation for send_cmd failed.\n");
650 return -VXI11_NULL_WRITE_RESP;
652 std::memcpy(send_cmd, cmd, len);
654 write_parms.lid = link->lid;
655 write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT;
656 write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
663 std::memset(&write_resp, 0,
sizeof(write_resp));
665 if (
static_cast<unsigned int>(bytes_left) <= link->maxRecvSize) {
666 write_parms.flags = 8;
667 write_parms.data.data_len = bytes_left;
669 write_parms.flags = 0;
674 if (link->maxRecvSize > 0) {
675 write_parms.data.data_len = link->maxRecvSize;
677 write_parms.data.data_len = 4096;
680 write_parms.data.data_val = send_cmd + (len - bytes_left);
682 if (device_write_1(&write_parms, &write_resp, client) != RPC_SUCCESS) {
684 return -VXI11_NULL_WRITE_RESP;
690 if (write_resp.error != 0) {
691 std::fprintf(stderr,
"vxi11_user: write error: %d\n",
static_cast<int>(write_resp.error));
693 return -(write_resp.error);
695 bytes_left -= write_resp.size;
696 }
while (bytes_left > 0);
703 return clnt_call(clnt, device_write,
704 reinterpret_cast<xdrproc_t
>(xdr_Device_WriteParms),
reinterpret_cast<caddr_t
>(argp),
705 reinterpret_cast<xdrproc_t
>(xdr_Device_WriteResp),
reinterpret_cast<caddr_t
>(clnt_res),
710 if (!xdr_Device_Link(xdrs, &objp->lid))
712 if (!xdr_u_long(xdrs, &objp->io_timeout))
714 if (!xdr_u_long(xdrs, &objp->lock_timeout))
716 if (!xdr_Device_Flags(xdrs, &objp->flags))
718 if (!xdr_bytes(xdrs, &objp->data.data_val,
reinterpret_cast<u_int *
>(&objp->data.data_len), ~0))
724 if (!xdr_Device_ErrorCode(xdrs, &objp->error))
726 if (!xdr_u_long(xdrs, &objp->size))
731bool_t xdr_Device_Flags(XDR *xdrs, Device_Flags *objp) {
732 return xdr_long(xdrs, objp);
736 return xdr_Device_ErrorCode(xdrs, &objp->error);
739int agilent_set_averages(
CLINK *clink,
int no_averages) {
742 if (no_averages <= 0) {
743 return vxi11_send(clink,
":ACQ:AVER 0");
745 std::snprintf(cmd,
sizeof(cmd),
":ACQ:COUNT %d", no_averages);
746 if (vxi11_send(clink, cmd) != 0) {
747 std::fprintf(stderr,
"Warning: Failed to set acquisition count.\n");
750 return vxi11_send(clink,
":ACQ:AVER 1");
754void agilent_set_for_auto(
CLINK *clink) {
755 vxi11_send(clink,
":ACQ:SRAT:AUTO 1;:ACQ:POINTS:AUTO 1;:RUN");
758int vxi11_close_device(
const char *ip,
CLINK *clink) {
763 for (l = 0; l < VXI11_MAX_CLIENTS; l++) {
764 if (std::strcmp(ip, VXI11_IP_ADDRESS[l]) == 0) {
770 if (device_no == -1) {
771 std::fprintf(stderr,
"vxi11_close_device: error: No record of opening device with IP %s.\n", ip);
775 if (VXI11_LINK_COUNT[device_no] > 1) {
776 ret = vxi11_close_link(ip, clink->client, clink->link);
777 VXI11_LINK_COUNT[device_no]--;
782 ret = vxi11_close_device(ip, clink->client, clink->link);
788int vxi11_close_device(
const char *ip, CLIENT *client,
VXI11_LINK *link) {
791 ret = vxi11_close_link(ip, client, link);
793 clnt_destroy(client);
798int vxi11_close_link(
const char *ip, CLIENT *client,
VXI11_LINK *link) {
800 std::memset(&dev_error, 0,
sizeof(dev_error));
802 if (destroy_link_1(&link->lid, &dev_error, client) != RPC_SUCCESS) {
804 clnt_perror(client,
const_cast<char *
>(ip));
806 clnt_perror(client, ip);
814enum clnt_stat destroy_link_1(Device_Link *argp,
Device_Error *clnt_res, CLIENT *clnt) {
815 return clnt_call(clnt, destroy_link,
816 reinterpret_cast<xdrproc_t
>(xdr_Device_Link),
reinterpret_cast<caddr_t
>(argp),
817 reinterpret_cast<xdrproc_t
>(xdr_Device_Error),
reinterpret_cast<caddr_t
>(clnt_res),
821double vxi11_obtain_double_value(
CLINK *clink,
const char *cmd) {
822 return vxi11_obtain_double_value(clink, cmd, VXI11_READ_TIMEOUT);
825double vxi11_obtain_double_value(
CLINK *clink,
const char *cmd,
unsigned long timeout) {
828 if (vxi11_send_and_receive(clink, cmd, buf,
sizeof(buf), timeout) != 0) {
829 std::fprintf(stderr,
"Warning: Failed to obtain double value for command '%s'. Returning 0.0.\n", cmd);
832 val = std::strtod(buf,
nullptr);
836long vxi11_send_and_receive(
CLINK *clink,
const char *cmd,
char *buf,
unsigned long buf_len,
unsigned long timeout) {
840 ret = vxi11_send(clink, cmd);
842 if (ret != -VXI11_NULL_WRITE_RESP) {
843 std::fprintf(stderr,
"Error: Could not send command '%s'. Function vxi11_send returned %d.\n", cmd, ret);
846 std::fprintf(stderr,
"Info: VXI11_NULL_WRITE_RESP in vxi11_send_and_receive, resending query.\n");
850 bytes_returned = vxi11_receive(clink, buf, buf_len, timeout);
851 if (bytes_returned <= 0) {
852 if (bytes_returned > -VXI11_NULL_READ_RESP) {
853 std::fprintf(stderr,
"Error: Problem reading reply for command '%s'. Function vxi11_receive returned %ld.\n", cmd, bytes_returned);
856 std::fprintf(stderr,
"Info: VXI11_NULL_READ_RESP in vxi11_send_and_receive, resending query.\n");
859 }
while (bytes_returned == -VXI11_NULL_READ_RESP || ret == -VXI11_NULL_WRITE_RESP);
863long vxi11_receive(CLIENT *client,
VXI11_LINK *link,
char *buffer,
unsigned long len,
unsigned long timeout) {
868 read_parms.lid = link->lid;
869 read_parms.requestSize = len;
870 read_parms.io_timeout = timeout;
871 read_parms.lock_timeout = timeout;
872 read_parms.flags = 0;
873 read_parms.termChar = 0;
876 std::memset(&read_resp, 0,
sizeof(read_resp));
878 read_resp.data.data_val = buffer + curr_pos;
879 read_parms.requestSize = len - curr_pos;
881 if (device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) {
882 return -VXI11_NULL_READ_RESP;
886 if (read_resp.error != 0) {
896 std::fprintf(stderr,
"vxi11_user: read error: %d\n",
static_cast<int>(read_resp.error));
897 return -(read_resp.error);
900 if ((
static_cast<unsigned long>(curr_pos + read_resp.data.data_len) <= len)) {
901 curr_pos += read_resp.data.data_len;
903 if ((read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT)) {
905 }
else if ((
static_cast<unsigned long>(curr_pos) == len)) {
906 std::fprintf(stderr,
"vxi11_user: read error: buffer too small. Read %ld bytes without hitting terminator.\n", curr_pos);
913long vxi11_receive(
CLINK *clink,
char *buffer,
unsigned long len) {
914 return vxi11_receive(clink, buffer, len, VXI11_READ_TIMEOUT);
917long vxi11_receive(
CLINK *clink,
char *buffer,
unsigned long len,
unsigned long timeout) {
918 return vxi11_receive(clink->client, clink->link, buffer, len, timeout);
922 return clnt_call(clnt, device_read,
923 reinterpret_cast<xdrproc_t
>(xdr_Device_ReadParms),
reinterpret_cast<caddr_t
>(argp),
924 reinterpret_cast<xdrproc_t
>(xdr_Device_ReadResp),
reinterpret_cast<caddr_t
>(clnt_res),
929#if defined(SOLARIS) && !defined(_LP64)
935 if (xdrs->x_op == XDR_ENCODE) {
936 if (!xdr_Device_Link(xdrs, &objp->lid))
938 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
939 if (buf ==
nullptr) {
940 if (!xdr_u_long(xdrs, &objp->requestSize))
942 if (!xdr_u_long(xdrs, &objp->io_timeout))
944 if (!xdr_u_long(xdrs, &objp->lock_timeout))
948 IXDR_PUT_U_INT32(buf, objp->requestSize);
949 IXDR_PUT_U_INT32(buf, objp->io_timeout);
950 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
952 if (!xdr_Device_Flags(xdrs, &objp->flags))
954 if (!xdr_char(xdrs, &objp->termChar))
957 }
else if (xdrs->x_op == XDR_DECODE) {
958 if (!xdr_Device_Link(xdrs, &objp->lid))
960 buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
961 if (buf ==
nullptr) {
962 if (!xdr_u_long(xdrs, &objp->requestSize))
964 if (!xdr_u_long(xdrs, &objp->io_timeout))
966 if (!xdr_u_long(xdrs, &objp->lock_timeout))
970 objp->requestSize = IXDR_GET_U_INT32(buf);
971 objp->io_timeout = IXDR_GET_U_INT32(buf);
972 objp->lock_timeout = IXDR_GET_U_INT32(buf);
974 if (!xdr_Device_Flags(xdrs, &objp->flags))
976 if (!xdr_char(xdrs, &objp->termChar))
981 if (!xdr_Device_Link(xdrs, &objp->lid))
983 if (!xdr_u_long(xdrs, &objp->requestSize))
985 if (!xdr_u_long(xdrs, &objp->io_timeout))
987 if (!xdr_u_long(xdrs, &objp->lock_timeout))
989 if (!xdr_Device_Flags(xdrs, &objp->flags))
991 if (!xdr_char(xdrs, &objp->termChar))
997 if (!xdr_Device_ErrorCode(xdrs, &objp->error))
999 if (!xdr_long(xdrs, &objp->reason))
1001 if (!xdr_bytes(xdrs, &objp->data.data_val,
reinterpret_cast<u_int *
>(&objp->data.data_len), ~0))
1006long vxi11_obtain_long_value(
CLINK *clink,
const char *cmd,
unsigned long timeout) {
1008 if (vxi11_send_and_receive(clink, cmd, buf,
sizeof(buf), timeout) != 0) {
1009 std::fprintf(stderr,
"Warning: Failed to obtain long value for command '%s'. Returning 0.\n", cmd);
1012 return std::strtol(buf,
nullptr, 10);
1016long vxi11_obtain_long_value(
CLINK *clink,
const char *cmd) {
1017 return vxi11_obtain_long_value(clink, cmd, VXI11_READ_TIMEOUT);
1020long agilent_get_data(
CLINK *clink,
char chan,
char *buf,
unsigned long buf_len,
unsigned long timeout) {
1021 return agilent_get_data(clink, chan, 1, buf, buf_len, timeout);
1024long agilent_get_data(
CLINK *clink,
char chan,
int digitise,
char *buf,
unsigned long buf_len,
unsigned long timeout) {
1025 char source[20] = {0};
1026 char cmd[256] = {0};
1028 long bytes_returned = 0;
1030 agilent_scope_channel_str(chan, source);
1031 std::snprintf(cmd,
sizeof(cmd),
":WAV:SOURCE %s", source);
1032 ret = vxi11_send(clink, cmd);
1034 std::fprintf(stderr,
"Error: Could not send ':WAV:SOURCE %s' command.\n", source);
1038 if (digitise != 0) {
1039 ret = vxi11_send(clink,
":DIG");
1041 std::fprintf(stderr,
"Warning: Failed to digitize.\n");
1046 ret = vxi11_send(clink,
":WAV:DATA?");
1048 std::fprintf(stderr,
"Warning: Failed to send ':WAV:DATA?' command.\n");
1051 bytes_returned = vxi11_receive_data_block(clink, buf, buf_len, timeout);
1052 }
while (bytes_returned == -VXI11_NULL_READ_RESP);
1056 return bytes_returned;
1059int agilent_get_preamble(
CLINK *clink,
char *buf,
unsigned long buf_len) {
1061 long bytes_returned;
1063 ret = vxi11_send(clink,
":WAV:PRE?");
1065 std::fprintf(stderr,
"Error: Could not send ':WAV:PRE?' command.\n");
1069 bytes_returned = vxi11_receive(clink, buf, buf_len);
1071 return static_cast<int>(bytes_returned);
1074void agilent_scope_channel_str(
char chan,
char *source) {
1078 std::strcpy(source,
"FUNC1");
1082 std::strcpy(source,
"FUNC2");
1086 std::strcpy(source,
"FUNC3");
1090 std::strcpy(source,
"FUNC4");
1093 std::strcpy(source,
"CHAN1");
1096 std::strcpy(source,
"CHAN2");
1099 std::strcpy(source,
"CHAN3");
1102 std::strcpy(source,
"CHAN4");
1105 std::fprintf(stderr,
"Warning: Unknown channel '%c'. Using channel 1.\n", chan);
1106 std::strcpy(source,
"CHAN1");
1111long vxi11_receive_data_block(
CLINK *clink,
char *buffer,
unsigned long len,
unsigned long timeout) {
1114 unsigned long necessary_buffer_size;
1115 char *in_buffer =
nullptr;
1118 unsigned long returned_bytes = 0;
1120 char scan_cmd[20] = {0};
1121 necessary_buffer_size = len + 12;
1122 in_buffer =
new (std::nothrow)
char[necessary_buffer_size];
1124 std::fprintf(stderr,
"Error: Memory allocation for in_buffer failed.\n");
1127 ret = vxi11_receive(clink, in_buffer, necessary_buffer_size, timeout);
1132 if (in_buffer[0] !=
'#') {
1133 std::fprintf(stderr,
"vxi11_user: data block error: data block does not begin with '#'\n");
1134 std::fprintf(stderr,
"First 20 characters received were: '");
1135 for (l = 0; l < 20 && l < static_cast<int>(necessary_buffer_size); l++) {
1136 std::fprintf(stderr,
"%c", in_buffer[l]);
1138 std::fprintf(stderr,
"'\n");
1144 if (std::sscanf(in_buffer,
"#%1d", &ndigits) != 1) {
1145 std::fprintf(stderr,
"vxi11_user: Failed to parse number of digits in data block header.\n");
1152 std::snprintf(scan_cmd,
sizeof(scan_cmd),
"##%dlu", ndigits);
1153 if (std::sscanf(in_buffer, scan_cmd, &returned_bytes) != 1) {
1154 std::fprintf(stderr,
"vxi11_user: Failed to parse number of returned bytes.\n");
1158 if (returned_bytes > len) {
1159 std::fprintf(stderr,
"vxi11_user: Received more bytes than buffer can hold.\n");
1163 std::memcpy(buffer, in_buffer + (ndigits + 2), returned_bytes);
1165 return static_cast<long>(returned_bytes);
1172int agilent_set_for_capture(
CLINK *clink,
double s_rate,
long npoints,
unsigned long timeout) {
1173 long actual_npoints = 0;
1174 double time_range = 0.0;
1175 double auto_srat = 0.0;
1176 long auto_npoints = 0;
1177 double expected_s_rate = 0.0;
1178 double actual_s_rate = 0.0;
1180 char cmd[256] = {0};
1181 char etim_result[256] = {0};
1183 int not_enough_memory = 0;
1191 vxi11_send_and_receive(clink,
":ACQ:MODE?", etim_result,
sizeof(etim_result), VXI11_READ_TIMEOUT);
1194 if (std::strncmp(
"ETIM", etim_result, 4) == 0) {
1196 time_range = vxi11_obtain_double_value(clink,
":TIM:RANGE?");
1199 auto_npoints = vxi11_obtain_long_value(clink,
":ACQ:POINTS?");
1202 vxi11_send(clink,
":ACQ:POINTS:AUTO 0");
1205 npoints = auto_npoints;
1211 std::snprintf(cmd,
sizeof(cmd),
":ACQ:POINTS %ld", (2 * npoints) - 1);
1212 vxi11_send(clink, cmd);
1216 vxi11_send(clink,
":DIG");
1219 xinc = vxi11_obtain_double_value(clink,
":WAV:XINC?", timeout);
1222 actual_npoints =
static_cast<long>((time_range / xinc) + 0.5);
1226 std::snprintf(cmd,
sizeof(cmd),
":ACQ:POINTS %ld", actual_npoints);
1227 vxi11_send(clink, cmd);
1235 std::snprintf(cmd,
sizeof(cmd),
":ACQ:SRAT %G", (1 / xinc));
1236 vxi11_send(clink, cmd);
1253 auto_srat = vxi11_obtain_double_value(clink,
":ACQ:SRAT?");
1256 vxi11_send(clink,
":ACQ:SRAT:AUTO 0;:ACQ:POINTS:AUTO 0");
1259 time_range = vxi11_obtain_double_value(clink,
":TIM:RANGE?");
1269 s_rate =
static_cast<double>(npoints) / time_range;
1276 expected_s_rate = s_rate;
1284 std::snprintf(cmd,
sizeof(cmd),
":ACQ:SRAT %G", s_rate);
1285 vxi11_send(clink, cmd);
1288 actual_s_rate = vxi11_obtain_double_value(clink,
":ACQ:SRAT?");
1291 npoints =
static_cast<long>((time_range * actual_s_rate) + 0.5);
1296 std::snprintf(cmd,
sizeof(cmd),
":ACQ:POINTS %ld", npoints);
1297 vxi11_send(clink, cmd);
1300 actual_npoints = vxi11_obtain_long_value(clink,
":ACQ:POINTS?");
1302 if (actual_npoints < npoints) {
1303 not_enough_memory = 1;
1305 s_rate = s_rate * 0.75 * (
static_cast<double>(actual_npoints) /
static_cast<double>(npoints));
1307 not_enough_memory = 0;
1309 }
while (not_enough_memory == 1);
1312 if (actual_s_rate != expected_s_rate) {
1315 if (ret_val == -1) {
1326long agilent_calculate_no_of_bytes(
CLINK *clink,
char chan,
unsigned long timeout) {
1327 char cmd[256] = {0};
1328 char source[20] = {0};
1329 double hinterval = 0.0, time_range = 0.0;
1331 long no_of_bytes = 0;
1332 char etim_result[256] = {0};
1336 agilent_scope_channel_str(chan, source);
1337 std::snprintf(cmd,
sizeof(cmd),
":WAV:SOURCE %s", source);
1338 vxi11_send(clink, cmd);
1339 vxi11_send(clink,
":DIG");
1342 hinterval = vxi11_obtain_double_value(clink,
":WAV:XINC?", timeout);
1343 time_range = vxi11_obtain_double_value(clink,
":TIM:RANGE?");
1347 vxi11_send_and_receive(clink,
":ACQ:MODE?", etim_result,
sizeof(etim_result), VXI11_READ_TIMEOUT);
1349 if (std::strncmp(
"ETIM", etim_result, 4) == 0) {
1350 no_of_bytes =
static_cast<long>(2 * ((time_range / hinterval) + 0.5));
1352 srat = vxi11_obtain_double_value(clink,
":ACQ:SRAT?");
1354 no_of_bytes =
static_cast<long>(2 * (((time_range - (1 / srat)) / hinterval) + 1) + 0.5);
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.