SDDSlib
Loading...
Searching...
No Matches
agilentwaveform2sdds.cpp
1/*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * This file is distributed subject to a Software License Agreement found
7 * in the file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/*
11 *
12 $Log: not supported by cvs2svn $
13 Revision 1.3 2009/12/10 17:31:46 soliday
14 Changed so that it builds on 64bit solaris.
15
16 Revision 1.2 2009/10/26 18:40:26 soliday
17 Fixed issue on Mac computers.
18
19 Revision 1.1 2009/08/18 19:13:07 soliday
20 Agilent scope communication software based off of software from Steve Sharples
21 of the Univ. of Nottingham
22
23 *
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <rpc/rpc.h>
30#include <pthread.h>
31#include "SDDS.h"
32
33typedef long Device_Link;
34typedef long Device_Flags;
35typedef long Device_ErrorCode;
36
37struct Device_Error {
38 Device_ErrorCode error;
39};
40typedef struct Device_Error Device_Error;
41
42struct Create_LinkParms {
43 long clientId;
44 bool_t lockDevice;
45 u_long lock_timeout;
46 char *device;
47};
49
50struct Create_LinkResp {
51 Device_ErrorCode error;
52 Device_Link lid;
53 u_short abortPort;
54 u_long maxRecvSize;
55};
56typedef struct Create_LinkResp Create_LinkResp;
57
58struct Device_WriteParms {
59 Device_Link lid;
60 u_long io_timeout;
61 u_long lock_timeout;
62 Device_Flags flags;
63 struct {
64 u_int data_len;
65 char *data_val;
66 } data;
67};
69
70struct Device_WriteResp {
71 Device_ErrorCode error;
72 u_long size;
73};
75
76struct Device_ReadParms {
77 Device_Link lid;
78 u_long requestSize;
79 u_long io_timeout;
80 u_long lock_timeout;
81 Device_Flags flags;
82 char termChar;
83};
85
86struct Device_ReadResp {
87 Device_ErrorCode error;
88 long reason;
89 struct {
90 u_int data_len;
91 char *data_val;
92 } data;
93};
94typedef struct Device_ReadResp Device_ReadResp;
95
96#define create_link 10
97#define device_write 11
98#define device_read 12
99#define destroy_link 23
100
101#define VXI11_DEFAULT_TIMEOUT 10000 /* in ms */
102#define VXI11_READ_TIMEOUT 2000 /* in ms */
103#define VXI11_CLIENT CLIENT
104#define VXI11_LINK Create_LinkResp
105#define VXI11_MAX_CLIENTS 256 /* maximum no of unique IP addresses/clients */
106#define VXI11_NULL_READ_RESP 50 /* vxi11_receive() return value if a query
107 * times out ON THE INSTRUMENT (and so we have
108 * to resend the query again) */
109#define VXI11_NULL_WRITE_RESP 51 /* vxi11_send() return value if a sent command
110 * times out ON THE INSTURMENT. */
111
112struct CLINK {
113 VXI11_CLIENT *client;
114 VXI11_LINK *link;
115} ;
116typedef struct CLINK CLINK;
117
118#define DEVICE_CORE 0x0607AF
119#define DEVICE_CORE_VERSION 1
120#define RCV_END_BIT 0x04 // An end indicator has been read
121#define RCV_CHR_BIT 0x02 // A termchr is set in flags and a character which matches termChar is transferred
122
123
124char VXI11_IP_ADDRESS[VXI11_MAX_CLIENTS][20];
125CLIENT *VXI11_CLIENT_ADDRESS[VXI11_MAX_CLIENTS];
126int VXI11_DEVICE_NO = 0;
127int VXI11_LINK_COUNT[VXI11_MAX_CLIENTS];
128
129static struct timeval TIMEOUT = { 25, 0 };
130
131
132#ifndef BOOL
133#define BOOL int
134#endif
135#ifndef TRUE
136#define TRUE 1
137#endif
138#ifndef FALSE
139#define FALSE 0
140#endif
141
142BOOL sc(char *con,char *var);
143
144int agilent_init(CLINK *clink);
145int agilent_set_averages(CLINK *clink,
146 int no_averages);
147void agilent_set_for_auto(CLINK *clink);
148long agilent_get_data(CLINK *clink,
149 char chan,
150 char *buf,
151 unsigned long buf_len,
152 unsigned long timeout);
153long agilent_get_data(CLINK *clink,
154 char chan,
155 int digitise,
156 char *buf,
157 unsigned long buf_len,
158 unsigned long timeout);
159int agilent_get_preamble(CLINK *clink,
160 char* buf,
161 unsigned long buf_len);
162void agilent_scope_channel_str(char chan,
163 char *source);
164int agilent_set_for_capture(CLINK *clink,
165 double s_rate,
166 long npoints,
167 unsigned long timeout);
168long agilent_calculate_no_of_bytes(CLINK *clink,
169 char chan,
170 unsigned long timeout);
171
172int vxi11_open_device(const char *ip,
173 CLINK *clink);
174int vxi11_open_device(const char *ip,
175 CLINK *clink,
176 char *device);
177int vxi11_open_device(const char *ip,
178 CLIENT **client,
179 VXI11_LINK **link,
180 char *device);
181int vxi11_open_link(const char *ip,
182 CLIENT **client,
183 VXI11_LINK **link,
184 char *device);
185int vxi11_send(CLINK *clink,
186 const char *cmd);
187int vxi11_send(CLINK *clink,
188 const char *cmd,
189 unsigned long len);
190int vxi11_send(CLIENT *client,
191 VXI11_LINK *link,
192 const char *cmd);
193int vxi11_send(CLIENT *client,
194 VXI11_LINK *link,
195 const char *cmd,
196 unsigned long len);
197int vxi11_close_device(const char *ip,
198 CLINK *clink);
199int vxi11_close_device(const char *ip,
200 CLIENT *client,
201 VXI11_LINK *link);
202int vxi11_close_link(const char *ip,
203 CLIENT *client,
204 VXI11_LINK *link);
205double vxi11_obtain_double_value(CLINK *clink,
206 const char *cmd);
207double vxi11_obtain_double_value(CLINK *clink,
208 const char *cmd,
209 unsigned long timeout);
210long vxi11_send_and_receive(CLINK *clink,
211 const char *cmd,
212 char *buf,
213 unsigned long buf_len,
214 unsigned long timeout);
215long vxi11_receive(CLINK *clink,
216 char *buffer,
217 unsigned long len);
218long vxi11_receive(CLIENT *client,
219 VXI11_LINK *link,
220 char *buffer,
221 unsigned long len,
222 unsigned long timeout);
223long vxi11_receive(CLINK *clink,
224 char *buffer,
225 unsigned long len,
226 unsigned long timeout);
227long vxi11_obtain_long_value(CLINK *clink,
228 const char *cmd,
229 unsigned long timeout);
230long vxi11_obtain_long_value(CLINK *clink,
231 const char *cmd);
232long vxi11_receive_data_block(CLINK *clink,
233 char *buffer,
234 unsigned long len,
235 unsigned long timeout);
236
237enum clnt_stat create_link_1(Create_LinkParms *argp,
238 Create_LinkResp *clnt_res,
239 CLIENT *clnt);
240enum clnt_stat device_write_1(Device_WriteParms *argp,
241 Device_WriteResp *clnt_res,
242 CLIENT *clnt);
243enum clnt_stat destroy_link_1(Device_Link *argp,
244 Device_Error *clnt_res,
245 CLIENT *clnt);
246enum clnt_stat device_read_1(Device_ReadParms *argp,
247 Device_ReadResp *clnt_res,
248 CLIENT *clnt);
249
250bool_t xdr_Create_LinkParms (XDR *xdrs,
251 Create_LinkParms *objp);
252bool_t xdr_Create_LinkResp (XDR *xdrs,
253 Create_LinkResp *objp);
254bool_t xdr_Device_ErrorCode (XDR *xdrs,
255 Device_ErrorCode *objp);
256bool_t xdr_Device_Link (XDR *xdrs,
257 Device_Link *objp);
258bool_t xdr_Device_WriteParms (XDR *xdrs,
259 Device_WriteParms *objp);
260bool_t xdr_Device_WriteResp (XDR *xdrs,
261 Device_WriteResp *objp);
262bool_t xdr_Device_Flags (XDR *xdrs,
263 Device_Flags *objp);
264bool_t xdr_Device_Error (XDR *xdrs,
265 Device_Error *objp);
266bool_t xdr_Device_ReadParms (XDR *xdrs,
267 Device_ReadParms *objp);
268bool_t xdr_Device_ReadResp (XDR *xdrs,
269 Device_ReadResp *objp);
270
271int main(int argc,char **argv)
272{
273 static char *progname;
274 static char *serverIP;
275 char chnl; /* we use '1' to '4' for channels, and 'A' to 'D' for FUNC[1...4] */
276 FILE *f_wf;
277 char wfname[256];
278 long buf_size;
279 char *buf;
280 unsigned long timeout=10000; /* in ms (= 10 seconds) */
281
282 long bytes_returned;
283 BOOL got_ip=FALSE;
284 BOOL got_scope_channel=FALSE;
285 BOOL got_file=FALSE;
286 BOOL got_no_averages=FALSE;
287 int no_averages;
288 int index=1;
289 double s_rate=0;
290 long npoints=0;
291 double actual_s_rate;
292 long actual_npoints;
293 CLINK *clink; /* client link (actually a structure contining CLIENT and VXI11_LINK pointers) */
294
295 short val;
296 double vgain,voffset,hinterval,hoffset;
297 long i;
298
299
300
301 clink = new CLINK; /* allocate some memory */
302 progname = argv[0];
303
304 while(index<argc){
305 if(sc(argv[index],(char*)"-filename")||sc(argv[index],(char*)"-f")||sc(argv[index],(char*)"-file")){
306 snprintf(wfname,256,"%s.sdds",argv[++index]);
307 got_file=TRUE;
308 }
309
310 if(sc(argv[index],(char*)"-ip")||sc(argv[index],(char*)"-ip_address")||sc(argv[index],(char*)"-IP")){
311 serverIP = argv[++index];
312 got_ip = TRUE;
313 }
314
315 if(sc(argv[index],(char*)"-channel")||sc(argv[index],(char*)"-c")||sc(argv[index],(char*)"-scope_channel")){
316 sscanf(argv[++index],"%c",&chnl);
317 got_scope_channel=TRUE;
318 }
319
320 if(sc(argv[index],(char*)"-sample_rate")||sc(argv[index],(char*)"-s")||sc(argv[index],(char*)"-rate")){
321 sscanf(argv[++index],"%lg",&s_rate);
322 }
323
324 if(sc(argv[index],(char*)"-no_points")||sc(argv[index],(char*)"-n")||sc(argv[index],(char*)"-points")){
325 sscanf(argv[++index],"%ld",&npoints);
326 }
327
328 if(sc(argv[index],(char*)"-averages")||sc(argv[index],(char*)"-a")||sc(argv[index],(char*)"-aver")){
329 sscanf(argv[++index],"%d",&no_averages);
330 got_no_averages=TRUE;
331 }
332
333 if(sc(argv[index],(char*)"-timeout")||sc(argv[index],(char*)"-t")){
334 sscanf(argv[++index],"%lu",&timeout);
335 }
336
337 index++;
338 }
339
340 if(got_file==FALSE||got_scope_channel==FALSE||got_ip==FALSE){
341 printf("%s: grabs a waveform from an Agilent scope via ethernet, by Steve (June 06)\n",progname);
342 printf("Run using %s [arguments]\n\n",progname);
343 printf("REQUIRED ARGUMENTS:\n");
344 printf("-ip -ip_address -IP : IP address of scope (eg 128.243.74.232)\n");
345 printf("-f -filename -file : filename (without extension)\n");
346 printf("-c -scope_channel -channel : scope channel (1,2,3,4,A,B,C,D)\n");
347 printf("OPTIONAL ARGUMENTS:\n");
348 printf("-t -timeout : timout (in milliseconds)\n");
349 printf("-s -sample_rate -rate : set sample rate (eg 1e9 = 1GS/s)\n");
350 printf("-n -no_points -points : set minimum no of points\n");
351 printf("-a -averages -aver : set no of averages (<=0 means none)\n\n");
352 printf("OUTPUTS:\n");
353 printf("filename.sdds : ascii data of waveform\n\n");
354 printf("EXAMPLE:\n");
355 printf("%s -ip 128.243.74.232 -f output -c 2 -s 1e9\n",progname);
356 exit(1);
357 }
358
359 f_wf=fopen(wfname,"w");
360 if (f_wf != 0) {
361 if (vxi11_open_device(serverIP,clink) != 0) {
362 printf("Quitting...\n");
363 exit(2);
364 }
365
366 if (agilent_init(clink) !=0 ) {
367 printf("Quitting...\n");
368 exit(2);
369 }
370
371 agilent_set_for_capture(clink, s_rate, npoints, timeout);
372
373 if (got_no_averages == TRUE) agilent_set_averages(clink, no_averages);
374
375
376 buf_size = agilent_calculate_no_of_bytes(clink, chnl, timeout);
377 buf=new char[buf_size];
378
379 hinterval = vxi11_obtain_double_value(clink, ":WAV:XINC?", timeout);
380 hoffset = vxi11_obtain_double_value(clink, ":WAV:XORIGIN?");
381 vgain = vxi11_obtain_double_value(clink, ":WAV:YINC?");
382 voffset = vxi11_obtain_double_value(clink, ":WAV:YORIGIN?");
383
384 bytes_returned = agilent_get_data(clink, chnl, 0, buf, buf_size, timeout);
385 if (bytes_returned <=0) {
386 printf("Problem reading the data, quitting...\n");
387 exit(2);
388 }
389
390 actual_s_rate = vxi11_obtain_double_value(clink, ":ACQ:SRAT?");
391 actual_npoints = vxi11_obtain_long_value(clink, ":ACQ:POINTS?");
392 printf("Sample rate used: %g (%g GSa/s); acquisition points: %ld\n",actual_s_rate, (actual_s_rate/1e9),actual_npoints);
393
394 agilent_set_for_auto(clink);
395
396 fprintf(f_wf, "SDDS1\n");
397 fprintf(f_wf, "&parameter name=VerticalGain, type=double, &end\n");
398 fprintf(f_wf, "&parameter name=VerticalOffset, type=double, &end\n");
399 fprintf(f_wf, "&parameter name=HorizontalInterval, type=double, &end\n");
400 fprintf(f_wf, "&parameter name=HorizontalOffset, type=double, &end\n");
401 fprintf(f_wf, "&column name=Index, type=long, &end\n");
402 fprintf(f_wf, "&column name=Waveform, type=double, &end\n");
403 fprintf(f_wf, "&column name=Timebase, type=double, &end\n");
404 fprintf(f_wf, "&column name=DelayedTimebase, type=double, &end\n");
405 fprintf(f_wf, "&data mode=ascii, &end\n");
406 fprintf(f_wf, "%lg\n", vgain);
407 fprintf(f_wf, "%lg\n", voffset);
408 fprintf(f_wf, "%lg\n", hinterval);
409 fprintf(f_wf, "%lg\n", hoffset);
410 fprintf(f_wf, "\t%ld\n", bytes_returned / 2);
411
412 for (i=0; i < bytes_returned; i += 2) {
413 *((char*)(&val)) = buf[i];
414 *((char*)(&val)+1) = buf[i+1];
415 fprintf(f_wf, "%ld %lg %lg %lg\n", (i/2), val * vgain - voffset, (i/2) * hinterval, (i/2) * hinterval + hoffset);
416 }
417
418 fclose(f_wf);
419 delete[] buf;
420
421 vxi11_close_device(serverIP,clink);
422
423 }
424 else {
425 printf("error: could not open file for writing, quitting...\n");
426 exit(3);
427 }
428}
429
430/* string compare (sc) function for parsing... ignore */
431BOOL sc(char *con,char *var) {
432 if(strcmp(con,var)==0){
433 return TRUE;
434 }
435 return FALSE;
436}
437
438int vxi11_open_device(const char *ip, CLINK *clink) {
439 char device[6];
440 strncpy(device,"inst0",6);
441 return vxi11_open_device(ip, clink, device);
442}
443
444int vxi11_open_device(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
445
446#ifdef darwin
447 *client = clnt_create((char*)ip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
448#else
449 *client = clnt_create(ip, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
450#endif
451
452 if (*client == NULL) {
453#ifdef darwin
454 clnt_pcreateerror((char*)ip);
455#else
456 clnt_pcreateerror(ip);
457#endif
458 return -1;
459 }
460
461 return vxi11_open_link(ip, client, link, device);
462}
463
464int vxi11_open_device(const char *ip, CLINK *clink, char *device) {
465 int ret;
466 int l;
467 int device_no=-1;
468
469 for (l=0; l<VXI11_MAX_CLIENTS; l++){
470 if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
471 device_no=l;
472 }
473 }
474
475 if (device_no < 0) {
476 if (VXI11_DEVICE_NO >= VXI11_MAX_CLIENTS) {
477 printf("Error: maximum of %d clients allowed\n",VXI11_MAX_CLIENTS);
478 ret = -VXI11_MAX_CLIENTS;
479 } else {
480 ret = vxi11_open_device(ip, &(clink->client), &(clink->link), device);
481 strncpy(VXI11_IP_ADDRESS[VXI11_DEVICE_NO],ip,20);
482 VXI11_CLIENT_ADDRESS[VXI11_DEVICE_NO] = clink->client;
483 VXI11_LINK_COUNT[VXI11_DEVICE_NO]=1;
484 VXI11_DEVICE_NO++;
485 }
486 } else {
487 clink->client = VXI11_CLIENT_ADDRESS[device_no];
488 ret = vxi11_open_link(ip, &(clink->client), &(clink->link), device);
489 VXI11_LINK_COUNT[device_no]++;
490 }
491 return ret;
492}
493
494int vxi11_open_link(const char *ip, CLIENT **client, VXI11_LINK **link, char *device) {
495
496 Create_LinkParms link_parms;
497
498 /* Set link parameters */
499 link_parms.clientId = (long) *client;
500 link_parms.lockDevice = 0;
501 link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
502 link_parms.device = device;
503
504 *link = (Create_LinkResp *) calloc(1, sizeof(Create_LinkResp));
505
506 if (create_link_1(&link_parms, *link, *client) != RPC_SUCCESS) {
507#ifdef darwin
508 clnt_perror(*client, (char*)ip);
509#else
510 clnt_perror(*client, ip);
511#endif
512 return -2;
513 }
514 return 0;
515}
516
517enum clnt_stat create_link_1(Create_LinkParms *argp, Create_LinkResp *clnt_res, CLIENT *clnt)
518{
519 return (clnt_call(clnt, create_link,
520 (xdrproc_t) xdr_Create_LinkParms, (caddr_t) argp,
521 (xdrproc_t) xdr_Create_LinkResp, (caddr_t) clnt_res,
522 TIMEOUT));
523}
524
525bool_t xdr_Create_LinkParms (XDR *xdrs, Create_LinkParms *objp)
526{
527
528#if defined(SOLARIS) && !defined(_LP64)
529 register long *buf;
530#else
531 register int32_t *buf;
532#endif
533
534 if (xdrs->x_op == XDR_ENCODE) {
535 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
536 if (buf == NULL) {
537 if (!xdr_long (xdrs, &objp->clientId))
538 return FALSE;
539 if (!xdr_bool (xdrs, &objp->lockDevice))
540 return FALSE;
541 if (!xdr_u_long (xdrs, &objp->lock_timeout))
542 return FALSE;
543
544 } else {
545 IXDR_PUT_INT32(buf, objp->clientId);
546 IXDR_PUT_BOOL(buf, objp->lockDevice);
547 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
548 }
549 if (!xdr_string (xdrs, &objp->device, ~0))
550 return FALSE;
551 return TRUE;
552 } else if (xdrs->x_op == XDR_DECODE) {
553 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
554 if (buf == NULL) {
555 if (!xdr_long (xdrs, &objp->clientId))
556 return FALSE;
557 if (!xdr_bool (xdrs, &objp->lockDevice))
558 return FALSE;
559 if (!xdr_u_long (xdrs, &objp->lock_timeout))
560 return FALSE;
561
562 } else {
563 objp->clientId = IXDR_GET_INT32(buf);
564 objp->lockDevice = IXDR_GET_BOOL(buf);
565 objp->lock_timeout = IXDR_GET_U_INT32(buf);
566 }
567 if (!xdr_string (xdrs, &objp->device, ~0))
568 return FALSE;
569 return TRUE;
570 }
571
572 if (!xdr_long (xdrs, &objp->clientId))
573 return FALSE;
574 if (!xdr_bool (xdrs, &objp->lockDevice))
575 return FALSE;
576 if (!xdr_u_long (xdrs, &objp->lock_timeout))
577 return FALSE;
578 if (!xdr_string (xdrs, &objp->device, ~0))
579 return FALSE;
580 return TRUE;
581}
582
583bool_t xdr_Create_LinkResp (XDR *xdrs, Create_LinkResp *objp)
584{
585 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
586 return FALSE;
587 if (!xdr_Device_Link (xdrs, &objp->lid))
588 return FALSE;
589 if (!xdr_u_short (xdrs, &objp->abortPort))
590 return FALSE;
591 if (!xdr_u_long (xdrs, &objp->maxRecvSize))
592 return FALSE;
593 return TRUE;
594}
595
596bool_t xdr_Device_ErrorCode (XDR *xdrs, Device_ErrorCode *objp)
597{
598 if (!xdr_long (xdrs, objp))
599 return FALSE;
600 return TRUE;
601}
602
603bool_t xdr_Device_Link (XDR *xdrs, Device_Link *objp)
604{
605 if (!xdr_long (xdrs, objp))
606 return FALSE;
607 return TRUE;
608}
609
610int agilent_init(CLINK *clink) {
611 int ret;
612 ret=vxi11_send(clink, ":SYSTEM:HEADER 0");
613 if(ret < 0) {
614 printf("Error: vxi11_send_and_receive: could not send cmd.\n");
615 printf(" The function vxi11_send returned %d. ",ret);
616 return ret;
617 }
618 vxi11_send(clink, ":ACQUIRE:COMPLETE 100");
619 if (SDDS_IsBigEndianMachine() == 0) {
620 vxi11_send(clink, ":WAVEFORM:BYTEORDER LSBFIRST");
621 } else {
622 vxi11_send(clink, ":WAVEFORM:BYTEORDER MSBFIRST");
623 }
624 vxi11_send(clink, ":WAVEFORM:FORMAT BINARY");
625 return 0;
626}
627
628int vxi11_send(CLINK *clink, const char *cmd) {
629 return vxi11_send(clink, cmd, strlen(cmd));
630}
631
632int vxi11_send(CLINK *clink, const char *cmd, unsigned long len) {
633 return vxi11_send(clink->client, clink->link, cmd, len);
634}
635
636int vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd) {
637 return vxi11_send(client, link, cmd, strlen(cmd));
638}
639
640int vxi11_send(CLIENT *client, VXI11_LINK *link, const char *cmd, unsigned long len) {
641 Device_WriteParms write_parms;
642 int bytes_left = (int)len;
643 char *send_cmd;
644
645 send_cmd = new char[len];
646 memcpy(send_cmd, cmd, len);
647
648 write_parms.lid = link->lid;
649 write_parms.io_timeout = VXI11_DEFAULT_TIMEOUT;
650 write_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
651
652 /* We can only write (link->maxRecvSize) bytes at a time, so we sit in a loop,
653 * writing a chunk at a time, until we're done. */
654
655 do {
656 Device_WriteResp write_resp;
657 memset(&write_resp, 0, sizeof(write_resp));
658
659 if ((unsigned int)bytes_left <= link->maxRecvSize) {
660 write_parms.flags = 8;
661 write_parms.data.data_len = bytes_left;
662 }
663 else {
664 write_parms.flags = 0;
665 /* We need to check that maxRecvSize is a sane value (ie >0). Believe it
666 * or not, on some versions of Agilent Infiniium scope firmware the scope
667 * returned "0", which breaks Rule B.6.3 of the VXI-11 protocol. Nevertheless
668 * we need to catch this, otherwise the program just hangs. */
669 if (link->maxRecvSize > 0) {
670 write_parms.data.data_len = link->maxRecvSize;
671 }
672 else {
673 write_parms.data.data_len = 4096; /* pretty much anything should be able to cope with 4kB */
674 }
675 }
676 write_parms.data.data_val = send_cmd + (len - bytes_left);
677
678 if(device_write_1(&write_parms, &write_resp, client) != RPC_SUCCESS) {
679 delete[] send_cmd;
680 return -VXI11_NULL_WRITE_RESP; /* The instrument did not acknowledge the write, just completely
681 dropped it. There was no vxi11 comms error as such, the
682 instrument is just being rude. Usually occurs when the instrument
683 is busy. If we don't check this first, then the following
684 line causes a seg fault */
685 }
686 if (write_resp . error != 0) {
687 printf("vxi11_user: write error: %d\n",(int)(write_resp . error));
688 delete[] send_cmd;
689 return -(write_resp . error);
690 }
691 bytes_left -= write_resp . size;
692 } while (bytes_left > 0);
693
694 delete[] send_cmd;
695 return 0;
696}
697
698enum clnt_stat device_write_1(Device_WriteParms *argp, Device_WriteResp *clnt_res, CLIENT *clnt)
699{
700 return (clnt_call(clnt, device_write,
701 (xdrproc_t) xdr_Device_WriteParms, (caddr_t) argp,
702 (xdrproc_t) xdr_Device_WriteResp, (caddr_t) clnt_res,
703 TIMEOUT));
704}
705
706bool_t xdr_Device_WriteParms (XDR *xdrs, Device_WriteParms *objp)
707{
708 if (!xdr_Device_Link (xdrs, &objp->lid))
709 return FALSE;
710 if (!xdr_u_long (xdrs, &objp->io_timeout))
711 return FALSE;
712 if (!xdr_u_long (xdrs, &objp->lock_timeout))
713 return FALSE;
714 if (!xdr_Device_Flags (xdrs, &objp->flags))
715 return FALSE;
716 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
717 return FALSE;
718 return TRUE;
719}
720
721bool_t xdr_Device_WriteResp (XDR *xdrs, Device_WriteResp *objp)
722{
723 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
724 return FALSE;
725 if (!xdr_u_long (xdrs, &objp->size))
726 return FALSE;
727 return TRUE;
728}
729
730bool_t xdr_Device_Flags (XDR *xdrs, Device_Flags *objp)
731{
732 if (!xdr_long (xdrs, objp))
733 return FALSE;
734 return TRUE;
735}
736
737int agilent_set_averages(CLINK *clink, int no_averages) {
738 char cmd[256];
739
740 if (no_averages <= 0) {
741 return vxi11_send(clink, ":ACQ:AVER 0");
742 }
743 else {
744 sprintf(cmd, ":ACQ:COUNT %d", no_averages);
745 vxi11_send(clink, cmd);
746 return vxi11_send(clink, ":ACQ:AVER 1");
747 }
748}
749
750void agilent_set_for_auto(CLINK *clink) {
751 vxi11_send(clink, ":ACQ:SRAT:AUTO 1;:ACQ:POINTS:AUTO 1;:RUN");
752}
753
754
755int vxi11_close_device(const char *ip, CLINK *clink) {
756 int l,ret;
757 int device_no = -1;
758
759 /* Which instrument are we referring to? */
760 for (l=0; l<VXI11_MAX_CLIENTS; l++){
761 if (strcmp(ip,VXI11_IP_ADDRESS[l]) == 0 ) {
762 device_no=l;
763 }
764 }
765 /* Something's up if we can't find the IP address! */
766 if (device_no == -1) {
767 printf("vxi11_close_device: error: I have no record of you ever opening device\n");
768 printf(" with IP address %s\n",ip);
769 ret = -4;
770 }
771 else { /* Found the IP, there's more than one link to that instrument,
772 * so keep track and just close the link */
773 if (VXI11_LINK_COUNT[device_no] > 1 ) {
774 ret = vxi11_close_link(ip,clink->client, clink->link);
775 VXI11_LINK_COUNT[device_no]--;
776 }
777 /* Found the IP, it's the last link, so close the device (link
778 * AND client) */
779 else {
780 ret = vxi11_close_device(ip, clink->client, clink->link);
781 }
782 }
783 return ret;
784}
785
786int vxi11_close_device(const char *ip, CLIENT *client, VXI11_LINK *link) {
787 int ret;
788
789 ret = vxi11_close_link(ip, client, link);
790
791 clnt_destroy(client);
792
793 return ret;
794}
795
796int vxi11_close_link(const char *ip, CLIENT *client, VXI11_LINK *link) {
797 Device_Error dev_error;
798 memset(&dev_error, 0, sizeof(dev_error));
799
800 if (destroy_link_1(&link->lid, &dev_error, client) != RPC_SUCCESS) {
801#ifdef darwin
802 clnt_perror(client,(char*)ip);
803#else
804 clnt_perror(client,ip);
805#endif
806 return -1;
807 }
808
809 return 0;
810}
811
812enum clnt_stat destroy_link_1(Device_Link *argp, Device_Error *clnt_res, CLIENT *clnt)
813{
814 return (clnt_call(clnt, destroy_link,
815 (xdrproc_t) xdr_Device_Link, (caddr_t) argp,
816 (xdrproc_t) xdr_Device_Error, (caddr_t) clnt_res,
817 TIMEOUT));
818}
819
820bool_t xdr_Device_Error (XDR *xdrs, Device_Error *objp)
821{
822 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
823 return FALSE;
824 return TRUE;
825}
826
827double vxi11_obtain_double_value(CLINK *clink, const char *cmd) {
828 return vxi11_obtain_double_value(clink, cmd, VXI11_READ_TIMEOUT);
829}
830
831double vxi11_obtain_double_value(CLINK *clink, const char *cmd, unsigned long timeout) {
832 char buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
833 double val;
834 memset(buf, 0, 50);
835 if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
836 printf("Returning 0.0\n");
837 return 0.0;
838 }
839 val = strtod(buf, (char **)NULL);
840 return val;
841}
842
843long vxi11_send_and_receive(CLINK *clink, const char *cmd, char *buf, unsigned long buf_len, unsigned long timeout) {
844 int ret;
845 long bytes_returned;
846 do {
847 ret = vxi11_send(clink, cmd);
848 if (ret != 0) {
849 if (ret != -VXI11_NULL_WRITE_RESP) {
850 printf("Error: vxi11_send_and_receive: could not send cmd.\n");
851 printf(" The function vxi11_send returned %d. ",ret);
852 return -1;
853 }
854 else printf("(Info: VXI11_NULL_WRITE_RESP in vxi11_send_and_receive, resending query)\n");
855 }
856
857 bytes_returned = vxi11_receive(clink, buf, buf_len, timeout);
858 if (bytes_returned <= 0) {
859 if (bytes_returned >-VXI11_NULL_READ_RESP) {
860 printf("Error: vxi11_send_and_receive: problem reading reply.\n");
861 printf(" The function vxi11_receive returned %ld. ",bytes_returned);
862 return -2;
863 }
864 else printf("(Info: VXI11_NULL_READ_RESP in vxi11_send_and_receive, resending query)\n");
865 }
866 } while (bytes_returned == -VXI11_NULL_READ_RESP || ret == -VXI11_NULL_WRITE_RESP);
867 return 0;
868}
869
870long vxi11_receive(CLIENT *client, VXI11_LINK *link, char *buffer, unsigned long len, unsigned long timeout) {
871 Device_ReadParms read_parms;
872 Device_ReadResp read_resp;
873 long curr_pos = 0;
874
875 read_parms.lid = link->lid;
876 read_parms.requestSize = len;
877 read_parms.io_timeout = timeout; /* in ms */
878 read_parms.lock_timeout = timeout; /* in ms */
879 read_parms.flags = 0;
880 read_parms.termChar = 0;
881
882 do {
883 memset(&read_resp, 0, sizeof(read_resp));
884
885 read_resp.data.data_val = buffer + curr_pos;
886 read_parms.requestSize = len - curr_pos; // Never request more total data than originally specified in len
887
888 if(device_read_1(&read_parms, &read_resp, client) != RPC_SUCCESS) {
889 return -VXI11_NULL_READ_RESP; /* there is nothing to read. Usually occurs after sending a query
890 which times out on the instrument. If we don't check this first,
891 then the following line causes a seg fault */
892 }
893 if (read_resp . error != 0) {
894 /* Read failed for reason specified in error code.
895 * 0 no error
896 * 4 invalid link identifier
897 * 11 device locked by another link
898 * 15 I/O timeout
899 * 17 I/O error
900 * 23 abort
901 */
902
903 printf("vxi11_user: read error: %d\n",(int)(read_resp . error));
904 return -(read_resp . error);
905 }
906
907 if((unsigned long)(curr_pos + read_resp . data.data_len) <= len) {
908 curr_pos += read_resp . data.data_len;
909 }
910 if( (read_resp.reason & RCV_END_BIT) || (read_resp.reason & RCV_CHR_BIT) ) {
911 break;
912 }
913 else if( (unsigned long)curr_pos == len ) {
914 printf("xvi11_user: read error: buffer too small. Read %ld bytes without hitting terminator.\n", curr_pos );
915 return -100;
916 }
917 } while(1);
918 return (curr_pos); /*actual number of bytes received*/
919
920}
921
922long vxi11_receive(CLINK *clink, char *buffer, unsigned long len) {
923 return vxi11_receive(clink, buffer, len, VXI11_READ_TIMEOUT);
924}
925
926long vxi11_receive(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
927 return vxi11_receive(clink->client, clink->link, buffer, len, timeout);
928}
929
930enum clnt_stat device_read_1(Device_ReadParms *argp, Device_ReadResp *clnt_res, CLIENT *clnt)
931{
932 return (clnt_call(clnt, device_read,
933 (xdrproc_t) xdr_Device_ReadParms, (caddr_t) argp,
934 (xdrproc_t) xdr_Device_ReadResp, (caddr_t) clnt_res,
935 TIMEOUT));
936}
937
938bool_t xdr_Device_ReadParms (XDR *xdrs, Device_ReadParms *objp)
939{
940#if defined(SOLARIS) && !defined(_LP64)
941 register long *buf;
942#else
943 register int32_t *buf;
944#endif
945
946 if (xdrs->x_op == XDR_ENCODE) {
947 if (!xdr_Device_Link (xdrs, &objp->lid))
948 return FALSE;
949 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
950 if (buf == NULL) {
951 if (!xdr_u_long (xdrs, &objp->requestSize))
952 return FALSE;
953 if (!xdr_u_long (xdrs, &objp->io_timeout))
954 return FALSE;
955 if (!xdr_u_long (xdrs, &objp->lock_timeout))
956 return FALSE;
957
958 } else {
959 IXDR_PUT_U_INT32(buf, objp->requestSize);
960 IXDR_PUT_U_INT32(buf, objp->io_timeout);
961 IXDR_PUT_U_INT32(buf, objp->lock_timeout);
962 }
963 if (!xdr_Device_Flags (xdrs, &objp->flags))
964 return FALSE;
965 if (!xdr_char (xdrs, &objp->termChar))
966 return FALSE;
967 return TRUE;
968 } else if (xdrs->x_op == XDR_DECODE) {
969 if (!xdr_Device_Link (xdrs, &objp->lid))
970 return FALSE;
971 buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT);
972 if (buf == NULL) {
973 if (!xdr_u_long (xdrs, &objp->requestSize))
974 return FALSE;
975 if (!xdr_u_long (xdrs, &objp->io_timeout))
976 return FALSE;
977 if (!xdr_u_long (xdrs, &objp->lock_timeout))
978 return FALSE;
979
980 } else {
981 objp->requestSize = IXDR_GET_U_INT32(buf);
982 objp->io_timeout = IXDR_GET_U_INT32(buf);
983 objp->lock_timeout = IXDR_GET_U_INT32(buf);
984 }
985 if (!xdr_Device_Flags (xdrs, &objp->flags))
986 return FALSE;
987 if (!xdr_char (xdrs, &objp->termChar))
988 return FALSE;
989 return TRUE;
990 }
991
992 if (!xdr_Device_Link (xdrs, &objp->lid))
993 return FALSE;
994 if (!xdr_u_long (xdrs, &objp->requestSize))
995 return FALSE;
996 if (!xdr_u_long (xdrs, &objp->io_timeout))
997 return FALSE;
998 if (!xdr_u_long (xdrs, &objp->lock_timeout))
999 return FALSE;
1000 if (!xdr_Device_Flags (xdrs, &objp->flags))
1001 return FALSE;
1002 if (!xdr_char (xdrs, &objp->termChar))
1003 return FALSE;
1004 return TRUE;
1005}
1006
1007bool_t xdr_Device_ReadResp (XDR *xdrs, Device_ReadResp *objp)
1008{
1009 if (!xdr_Device_ErrorCode (xdrs, &objp->error))
1010 return FALSE;
1011 if (!xdr_long (xdrs, &objp->reason))
1012 return FALSE;
1013 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
1014 return FALSE;
1015 return TRUE;
1016}
1017
1018long vxi11_obtain_long_value(CLINK *clink, const char *cmd, unsigned long timeout) {
1019 char buf[50]; /* 50=arbitrary length... more than enough for one number in ascii */
1020 memset(buf, 0, 50);
1021 if (vxi11_send_and_receive(clink, cmd, buf, 50, timeout) != 0) {
1022 printf("Returning 0\n");
1023 return 0;
1024 }
1025 return strtol(buf, (char **)NULL, 10);
1026}
1027
1028/* Lazy wrapper function with default read timeout */
1029long vxi11_obtain_long_value(CLINK *clink, const char *cmd) {
1030 return vxi11_obtain_long_value(clink, cmd, VXI11_READ_TIMEOUT);
1031}
1032
1033long agilent_get_data(CLINK *clink, char chan, char *buf, unsigned long buf_len, unsigned long timeout) {
1034 return agilent_get_data(clink, chan, 1, buf, buf_len, timeout);
1035}
1036
1037long agilent_get_data(CLINK *clink, char chan, int digitise, char *buf, unsigned long buf_len, unsigned long timeout) {
1038 char source[20];
1039 char cmd[256];
1040 int ret;
1041 long bytes_returned;
1042
1043 memset(source,0,20);
1044 agilent_scope_channel_str(chan, source);
1045 sprintf(cmd,":WAV:SOURCE %s",source);
1046 ret=vxi11_send(clink, cmd);
1047 if(ret < 0) {
1048 printf("error, could not send :WAV:SOURCE %s cmd, quitting...\n",source);
1049 return ret;
1050 }
1051
1052 if (digitise != 0) {
1053 ret=vxi11_send(clink, ":DIG");
1054 }
1055 memset(cmd,0,256);
1056 do {
1057 ret=vxi11_send(clink, ":WAV:DATA?");
1058 bytes_returned=vxi11_receive_data_block(clink, buf, buf_len, timeout);
1059 } while (bytes_returned == -VXI11_NULL_READ_RESP);
1060 /* We have to check for this after a :DIG because it could take a very long time */
1061 return bytes_returned;
1062}
1063
1064int agilent_get_preamble(CLINK *clink, char* buf, unsigned long buf_len) {
1065 int ret;
1066 long bytes_returned;
1067
1068 ret=vxi11_send(clink, ":WAV:PRE?");
1069 if(ret < 0) {
1070 printf("error, could not send :WAV:PRE? cmd, quitting...\n");
1071 return ret;
1072 }
1073
1074 bytes_returned=vxi11_receive(clink, buf, buf_len);
1075
1076 return (int) bytes_returned;
1077}
1078
1079void agilent_scope_channel_str(char chan, char *source) {
1080 switch (chan) {
1081 case 'A' :
1082 case 'a' : strcpy(source,"FUNC1");
1083 break;
1084 case 'B' :
1085 case 'b' : strcpy(source,"FUNC2");
1086 break;
1087 case 'C' :
1088 case 'c' : strcpy(source,"FUNC3");
1089 break;
1090 case 'D' :
1091 case 'd' : strcpy(source,"FUNC4");
1092 break;
1093 case '1' : strcpy(source,"CHAN1");
1094 break;
1095 case '2' : strcpy(source,"CHAN2");
1096 break;
1097 case '3' : strcpy(source,"CHAN3");
1098 break;
1099 case '4' : strcpy(source,"CHAN4");
1100 break;
1101 default : printf("error: unknown channel '%c', using channel 1\n",chan);
1102 strcpy(source,"CHAN1");
1103 break;
1104 }
1105}
1106
1107long vxi11_receive_data_block(CLINK *clink, char *buffer, unsigned long len, unsigned long timeout) {
1108 /* I'm not sure what the maximum length of this header is, I'll assume it's
1109 * 11 (#9 + 9 digits) */
1110 unsigned long necessary_buffer_size;
1111 char *in_buffer;
1112 int ret;
1113 int ndigits;
1114 unsigned long returned_bytes;
1115 int l;
1116 char scan_cmd[20];
1117 necessary_buffer_size=len+12;
1118 in_buffer=new char[necessary_buffer_size];
1119 ret=vxi11_receive(clink, in_buffer, necessary_buffer_size, timeout);
1120 if (ret < 0) return ret;
1121 if (in_buffer[0] != '#') {
1122 printf("vxi11_user: data block error: data block does not begin with '#'\n");
1123 printf("First 20 characters received were: '");
1124 for(l=0;l<20;l++) {
1125 printf("%c",in_buffer[l]);
1126 }
1127 printf("'\n");
1128 return -3;
1129 }
1130
1131 /* first find out how many digits */
1132 sscanf(in_buffer,"#%1d",&ndigits);
1133 /* some instruments, if there is a problem acquiring the data, return only "#0" */
1134 if (ndigits > 0) {
1135 /* now that we know, we can convert the next <ndigits> bytes into an unsigned long */
1136 sprintf(scan_cmd,"#%%1d%%%dlu",ndigits);
1137 sscanf(in_buffer,scan_cmd,&ndigits,&returned_bytes);
1138 memcpy(buffer, in_buffer+(ndigits+2), returned_bytes);
1139 delete[] in_buffer;
1140 return (long) returned_bytes;
1141 }
1142 else return 0;
1143}
1144
1145int agilent_set_for_capture(CLINK *clink, double s_rate, long npoints, unsigned long timeout) {
1146 long actual_npoints; /* actual number of points returned */
1147 double time_range;
1148 double auto_srat; /* sample rate whilst on auto setting */
1149 long auto_npoints; /* no of points whilst on auto setting */
1150 double expected_s_rate; /* based on s_rate passed to us, or npoints */
1151 double actual_s_rate; /* what it ends up as */
1152 double xinc; /* xincrement (only need for ETIM mode) */
1153 char cmd[256];
1154 char etim_result[256];
1155 int ret_val = 0;
1156 int not_enough_memory = 0;
1157
1158 /* First we need to find out if we're in "ETIM" (equivalent time) mode,
1159 * because things are done differently. You can't set the sample rate,
1160 * and if you query it, you get a meaningless answer. You must work out
1161 * what the effective sample rate is from the waveform xincrement. A
1162 * pain in the arse, quite frankly. */
1163
1164 vxi11_send_and_receive(clink, ":ACQ:MODE?", etim_result, 256, VXI11_READ_TIMEOUT);
1165
1166 /* Equivalent time (ETIM) mode: */
1167 if (strncmp("ETIM",etim_result,4) == 0) {
1168 /* Find out the time range displayed on the screen */
1169 time_range = vxi11_obtain_double_value(clink, ":TIM:RANGE?");
1170
1171 /* Find the xincrement, whilst we're still in auto (points) mode */
1172 auto_npoints = vxi11_obtain_long_value(clink, ":ACQ:POINTS?");
1173
1174 /* Set the no of acquisition points to manual */
1175 vxi11_send(clink, ":ACQ:POINTS:AUTO 0");
1176
1177 if (npoints <= 0) { // if we've not been passed a value for npoints
1178 npoints = auto_npoints;
1179 }
1180 /* Remember we want at LEAST the number of points specified.
1181 * To some extent, the xinc value is determined by the
1182 * number of points. So to get the best xinc value we ask
1183 * for double what we actually want. */
1184 sprintf(cmd, ":ACQ:POINTS %ld",(2*npoints)-1);
1185 vxi11_send(clink, cmd);
1186
1187 /* Unfortunately we have to do a :dig, to make sure our changes have
1188 * been registered */
1189 vxi11_send(clink, ":DIG");
1190
1191 /* Find the xincrement is now*/
1192 xinc = vxi11_obtain_double_value(clink, ":WAV:XINC?", timeout);
1193
1194 /* Work out the number of points there _should_ be to cover the time range */
1195 actual_npoints = (long) ( (time_range / xinc) + 0.5);
1196
1197 /* Set the number of points accordingly. Hopefully the
1198 * xincrement won't have changed! */
1199 sprintf(cmd, ":ACQ:POINTS %ld",actual_npoints);
1200 vxi11_send(clink, cmd);
1201
1202 /* This is a bit anal... we can work out very easily what the equivalent
1203 * sampling rate is (1 / xinc); the scope seems to store this value
1204 * somewhere, even though it doesn't use it. We may as well write it
1205 * to the scope, in case some user program asks for it while in
1206 * equivalent time mode. Should not be depended upon, though! */
1207
1208 sprintf(cmd, ":ACQ:SRAT %G", (1/xinc));
1209 vxi11_send(clink, cmd);
1210 }
1211
1212 /* Real time (RTIM, NORM or PDET) mode: */
1213 else {
1214 /* First find out what the sample rate is set to.
1215 * Each time you switch from auto to manual for either of these, the
1216 * scope remembers the values from last time you set these manually.
1217 * This is not very useful to us. We want to be able to set either the
1218 * sample rate (and derive npoints from that and the timebase), or the
1219 * minimum number of points (and derive the sample rate) or let
1220 * the scope choose sensible values for both of these. We only want to
1221 * capture the data for the time period displayed on the scope screen,
1222 * which is equal to the time range. If you leave the scope to do
1223 * everything auto, then it always acquires a bit more than what's on
1224 * the screen.
1225 */
1226 auto_srat = vxi11_obtain_double_value(clink, ":ACQ:SRAT?");
1227
1228 /* Set the sample rate (SRAT) and no of acquisition points to manual */
1229 vxi11_send(clink, ":ACQ:SRAT:AUTO 0;:ACQ:POINTS:AUTO 0");
1230
1231 /* Find out the time range displayed on the screen */
1232 time_range = vxi11_obtain_double_value(clink, ":TIM:RANGE?");
1233
1234 /* If we've not been passed a sample rate (ie s_rate <= 0) then... */
1235 if (s_rate <= 0 ) {
1236 /* ... if we've not been passed npoints, let scope set rate */
1237 if (npoints <= 0) {
1238 s_rate = auto_srat;
1239 }
1240 /* ... otherwise set the sample rate based on no of points. */
1241 else {
1242 s_rate = (double) npoints / time_range;
1243 }
1244 }
1245 /* We make a note here of what we're expecting the sample rate to be.
1246 * If it has to change for any reason (dodgy value, or not enough
1247 * memory) we will know about it.
1248 */
1249 expected_s_rate = s_rate;
1250
1251 /* Now we set the number of points to acquire. Of course, the scope
1252 * may not have enough memory to acquire all the points, so we just
1253 * sit in a loop, reducing the sample rate each time, until it's happy.
1254 */
1255 do {
1256 /* Send scope our desired sample rate. */
1257 sprintf(cmd, ":ACQ:SRAT %G",s_rate);
1258 vxi11_send(clink, cmd);
1259 /* Scope will choose next highest allowed rate.
1260 * Find out what this is */
1261 actual_s_rate = vxi11_obtain_double_value(clink, ":ACQ:SRAT?");
1262
1263 /* Calculate the number of points on display (and round up for rounding errors) */
1264 npoints = (long) ((time_range * actual_s_rate)+0.5);
1265
1266 /* Set the number of points accordingly */
1267 /* Note this won't necessarily be the no of points you receive, eg if you have
1268 * sin(x)/x interpolation turned on, you will probably get more. */
1269 sprintf(cmd, ":ACQ:POINTS %ld",npoints);
1270 vxi11_send(clink, cmd);
1271
1272 /* We should do a check, see if there's enough memory */
1273 actual_npoints = vxi11_obtain_long_value(clink, ":ACQ:POINTS?");
1274
1275 if (actual_npoints < npoints) {
1276 not_enough_memory = 1;
1277 ret_val = -1; /* We should report this fact to the calling function */
1278 s_rate = s_rate * 0.75 * (double) ( (double) actual_npoints / (double) npoints );
1279 }
1280 else {
1281 not_enough_memory = 0;
1282 }
1283 } while (not_enough_memory == 1);
1284 /* Will possibly remove the explicit printf's here, maybe leave it up to the
1285 * calling function to spot potential problems (the user may not care!) */
1286 if (actual_s_rate != expected_s_rate) {
1287 //printf("Warning: the sampling rate has been adjusted,\n");
1288 //printf("from %g to %g, because ", expected_s_rate, actual_s_rate);
1289 if (ret_val == -1) {
1290 //printf("there was not enough memory.\n");
1291 }
1292 else {
1293 //printf("because %g Sa/s is not a valid sample rate.\n",expected_s_rate);
1294 ret_val = -2;
1295 }
1296 }
1297 }
1298 return ret_val;
1299}
1300
1301long agilent_calculate_no_of_bytes(CLINK *clink, char chan, unsigned long timeout) {
1302 char cmd[256];
1303 char source[20];
1304 double hinterval,time_range;
1305 double srat;
1306 long no_of_bytes;
1307 char etim_result[256];
1308
1309 // First we need to digitize, to get the correct values for the
1310 // waveform data. This is a pain in the arse.
1311 agilent_scope_channel_str(chan, source);
1312 sprintf(cmd,":WAV:SOURCE %s",source);
1313 vxi11_send(clink, cmd);
1314 vxi11_send(clink, ":DIG");
1315
1316 /* Now find the info we need to calculate the number of points */
1317 hinterval = vxi11_obtain_double_value(clink, ":WAV:XINC?", timeout);
1318 time_range = vxi11_obtain_double_value(clink, ":TIM:RANGE?");
1319
1320 /* Are we in equivalent time (ETIM) mode? If so, the value of ACQ:SRAT will
1321 * be meaningless, and there's a different formula */
1322 vxi11_send_and_receive(clink, ":ACQ:MODE?", etim_result, 256, VXI11_READ_TIMEOUT);
1323 /* Equivalent time (ETIM) mode: */
1324 if (strncmp("ETIM",etim_result,4) == 0) {
1325 no_of_bytes = (long) ( 2*((time_range / hinterval) + 0.5) );
1326 }
1327 else {
1328 srat = vxi11_obtain_double_value(clink, ":ACQ:SRAT?");
1329
1330 no_of_bytes = (long) (2*(((time_range-(1/srat)) / hinterval)+1) + 0.5);
1331 /* 2x because 2 bytes per data point
1332 * +0.5 to round up when casting as a long
1333 * -(1/srat) and +1 so that both raw data, and interpolated (sinx/x) data works */
1334 }
1335 return no_of_bytes;
1336}
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
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.